mirror of
https://git.beihong.wang/wangbeihong/blog-source.git
synced 2026-04-23 16:23:04 +08:00
initial
This commit is contained in:
109
var/Widget/Contents/Post/Admin.php
Executable file
109
var/Widget/Contents/Post/Admin.php
Executable file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Widget\Contents\Post;
|
||||
|
||||
use Typecho\Cookie;
|
||||
use Typecho\Db;
|
||||
use Typecho\Db\Exception as DbException;
|
||||
use Typecho\Widget\Exception;
|
||||
use Widget\Base\Contents;
|
||||
use Widget\Contents\AdminTrait;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章管理列表组件
|
||||
*
|
||||
* @category typecho
|
||||
* @package Widget
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
*/
|
||||
class Admin extends Contents
|
||||
{
|
||||
use AdminTrait;
|
||||
|
||||
/**
|
||||
* 获取菜单标题
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception|DbException
|
||||
*/
|
||||
public function getMenuTitle(): string
|
||||
{
|
||||
if ($this->request->is('uid')) {
|
||||
return _t('%s的文章', $this->db->fetchObject($this->db->select('screenName')->from('table.users')
|
||||
->where('uid = ?', $this->request->filter('int')->get('uid')))->screenName);
|
||||
}
|
||||
|
||||
throw new Exception(_t('用户不存在'), 404);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行函数
|
||||
*
|
||||
* @throws DbException
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->initPage();
|
||||
|
||||
/** 构建基础查询 */
|
||||
$select = $this->select();
|
||||
|
||||
/** 如果具有编辑以上权限,可以查看所有文章,反之只能查看自己的文章 */
|
||||
if (!$this->user->pass('editor', true)) {
|
||||
$select->where('table.contents.authorId = ?', $this->user->uid);
|
||||
} else {
|
||||
if ($this->request->is('__typecho_all_posts=on')) {
|
||||
Cookie::set('__typecho_all_posts', 'on');
|
||||
} else {
|
||||
if ($this->request->is('__typecho_all_posts=off')) {
|
||||
Cookie::set('__typecho_all_posts', 'off');
|
||||
}
|
||||
|
||||
if ('on' != Cookie::get('__typecho_all_posts')) {
|
||||
$select->where(
|
||||
'table.contents.authorId = ?',
|
||||
$this->request->filter('int')->get('uid', $this->user->uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 按状态查询 */
|
||||
if ($this->request->is('status=draft')) {
|
||||
$select->where('table.contents.type = ?', 'post_draft');
|
||||
} elseif ($this->request->is('status=waiting')) {
|
||||
$select->where(
|
||||
'(table.contents.type = ? OR table.contents.type = ?) AND table.contents.status = ?',
|
||||
'post',
|
||||
'post_draft',
|
||||
'waiting'
|
||||
);
|
||||
} else {
|
||||
$select->where(
|
||||
'table.contents.type = ? OR table.contents.type = ?',
|
||||
'post',
|
||||
'post_draft'
|
||||
);
|
||||
}
|
||||
|
||||
/** 过滤分类 */
|
||||
if (null != ($category = $this->request->get('category'))) {
|
||||
$select->join('table.relationships', 'table.contents.cid = table.relationships.cid')
|
||||
->where('table.relationships.mid = ?', $category);
|
||||
}
|
||||
|
||||
$this->searchQuery($select);
|
||||
$this->countTotal($select);
|
||||
|
||||
/** 提交查询 */
|
||||
$select->order('table.contents.cid', Db::SORT_DESC)
|
||||
->page($this->currentPage, $this->parameter->pageSize);
|
||||
|
||||
$this->db->fetchAll($select, [$this, 'push']);
|
||||
}
|
||||
}
|
||||
77
var/Widget/Contents/Post/Date.php
Executable file
77
var/Widget/Contents/Post/Date.php
Executable file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Widget\Contents\Post;
|
||||
|
||||
use Typecho\Config;
|
||||
use Typecho\Db;
|
||||
use Typecho\Router;
|
||||
use Widget\Base;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按日期归档列表组件
|
||||
*
|
||||
* @author qining
|
||||
* @category typecho
|
||||
* @package Widget
|
||||
*/
|
||||
class Date extends Base
|
||||
{
|
||||
/**
|
||||
* @param Config $parameter
|
||||
*/
|
||||
protected function initParameter(Config $parameter)
|
||||
{
|
||||
$parameter->setDefault('format=Y-m&type=month&limit=0');
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化函数
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/** 设置参数默认值 */
|
||||
$this->parameter->setDefault('format=Y-m&type=month&limit=0');
|
||||
|
||||
$resource = $this->db->query($this->db->select('created')->from('table.contents')
|
||||
->where('type = ?', 'post')
|
||||
->where('table.contents.status = ?', 'publish')
|
||||
->where('table.contents.created < ?', $this->options->time)
|
||||
->order('table.contents.created', Db::SORT_DESC));
|
||||
|
||||
$offset = $this->options->timezone - $this->options->serverTimezone;
|
||||
$result = [];
|
||||
while ($post = $this->db->fetchRow($resource)) {
|
||||
$timeStamp = $post['created'] + $offset;
|
||||
$date = date($this->parameter->format, $timeStamp);
|
||||
|
||||
if (isset($result[$date])) {
|
||||
$result[$date]['count'] ++;
|
||||
} else {
|
||||
$result[$date]['year'] = date('Y', $timeStamp);
|
||||
$result[$date]['month'] = date('m', $timeStamp);
|
||||
$result[$date]['day'] = date('d', $timeStamp);
|
||||
$result[$date]['date'] = $date;
|
||||
$result[$date]['count'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->parameter->limit > 0) {
|
||||
$result = array_slice($result, 0, $this->parameter->limit);
|
||||
}
|
||||
|
||||
foreach ($result as $row) {
|
||||
$row['permalink'] = Router::url(
|
||||
'archive_' . $this->parameter->type,
|
||||
$row,
|
||||
$this->options->index
|
||||
);
|
||||
$this->push($row);
|
||||
}
|
||||
}
|
||||
}
|
||||
373
var/Widget/Contents/Post/Edit.php
Executable file
373
var/Widget/Contents/Post/Edit.php
Executable file
@@ -0,0 +1,373 @@
|
||||
<?php
|
||||
|
||||
namespace Widget\Contents\Post;
|
||||
|
||||
use Typecho\Common;
|
||||
use Typecho\Widget\Exception;
|
||||
use Widget\Base\Contents;
|
||||
use Widget\Base\Metas;
|
||||
use Widget\ActionInterface;
|
||||
use Typecho\Db\Exception as DbException;
|
||||
use Typecho\Date as TypechoDate;
|
||||
use Widget\Contents\EditTrait;
|
||||
use Widget\Contents\PrepareEditTrait;
|
||||
use Widget\Notice;
|
||||
use Widget\Service;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑文章组件
|
||||
*
|
||||
* @property-read array $draft
|
||||
*/
|
||||
class Edit extends Contents implements ActionInterface
|
||||
{
|
||||
use PrepareEditTrait;
|
||||
use EditTrait;
|
||||
|
||||
/**
|
||||
* 执行函数
|
||||
*
|
||||
* @throws Exception|DbException
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/** 必须为贡献者以上权限 */
|
||||
$this->user->pass('contributor');
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布文章
|
||||
*/
|
||||
public function writePost()
|
||||
{
|
||||
$contents = $this->request->from(
|
||||
'password',
|
||||
'allowComment',
|
||||
'allowPing',
|
||||
'allowFeed',
|
||||
'slug',
|
||||
'tags',
|
||||
'text',
|
||||
'visibility'
|
||||
);
|
||||
|
||||
$contents['category'] = $this->request->getArray('category');
|
||||
$contents['title'] = $this->request->get('title', _t('未命名文档'));
|
||||
$contents['created'] = $this->getCreated();
|
||||
|
||||
if ($this->request->is('markdown=1') && $this->options->markdown) {
|
||||
$contents['text'] = '<!--markdown-->' . $contents['text'];
|
||||
}
|
||||
|
||||
$contents = self::pluginHandle()->filter('write', $contents, $this);
|
||||
|
||||
if ($this->request->is('do=publish')) {
|
||||
/** 重新发布已经存在的文章 */
|
||||
$contents['type'] = 'post';
|
||||
$this->publish($contents);
|
||||
|
||||
// 完成发布插件接口
|
||||
self::pluginHandle()->call('finishPublish', $contents, $this);
|
||||
|
||||
/** 发送ping */
|
||||
$trackback = array_filter(
|
||||
array_unique(preg_split("/(\r|\n|\r\n)/", trim($this->request->get('trackback', ''))))
|
||||
);
|
||||
Service::alloc()->sendPing($this, $trackback);
|
||||
|
||||
/** 设置提示信息 */
|
||||
Notice::alloc()->set('post' == $this->type ?
|
||||
_t('文章 "<a href="%s">%s</a>" 已经发布', $this->permalink, $this->title) :
|
||||
_t('文章 "%s" 等待审核', $this->title), 'success');
|
||||
|
||||
/** 设置高亮 */
|
||||
Notice::alloc()->highlight($this->theId);
|
||||
|
||||
/** 获取页面偏移 */
|
||||
$pageQuery = $this->getPageOffsetQuery($this->cid);
|
||||
|
||||
/** 页面跳转 */
|
||||
$this->response->redirect(Common::url('manage-posts.php?' . $pageQuery, $this->options->adminUrl));
|
||||
} else {
|
||||
/** 保存文章 */
|
||||
$contents['type'] = 'post_draft';
|
||||
$draftId = $this->save($contents);
|
||||
|
||||
// 完成保存插件接口
|
||||
self::pluginHandle()->call('finishSave', $contents, $this);
|
||||
|
||||
/** 设置高亮 */
|
||||
Notice::alloc()->highlight($this->cid);
|
||||
|
||||
if ($this->request->isAjax()) {
|
||||
$created = new TypechoDate();
|
||||
$this->response->throwJson([
|
||||
'success' => 1,
|
||||
'time' => $created->format('H:i:s A'),
|
||||
'cid' => $this->cid,
|
||||
'draftId' => $draftId
|
||||
]);
|
||||
} else {
|
||||
/** 设置提示信息 */
|
||||
Notice::alloc()->set(_t('草稿 "%s" 已经被保存', $this->title), 'success');
|
||||
|
||||
/** 返回原页面 */
|
||||
$this->response->redirect(Common::url('write-post.php?cid=' . $this->cid, $this->options->adminUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取页面偏移的URL Query
|
||||
*
|
||||
* @param integer $cid 文章id
|
||||
* @param string|null $status 状态
|
||||
* @return string
|
||||
* @throws DbException
|
||||
*/
|
||||
protected function getPageOffsetQuery(int $cid, ?string $status = null): string
|
||||
{
|
||||
return 'page=' . $this->getPageOffset(
|
||||
'cid',
|
||||
$cid,
|
||||
'post',
|
||||
$status,
|
||||
$this->request->is('__typecho_all_posts=on') ? 0 : $this->user->uid
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记文章
|
||||
*
|
||||
* @throws DbException
|
||||
*/
|
||||
public function markPost()
|
||||
{
|
||||
$status = $this->request->get('status');
|
||||
$statusList = [
|
||||
'publish' => _t('公开'),
|
||||
'private' => _t('私密'),
|
||||
'hidden' => _t('隐藏'),
|
||||
'waiting' => _t('待审核')
|
||||
];
|
||||
|
||||
if (!isset($statusList[$status])) {
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
$posts = $this->request->filter('int')->getArray('cid');
|
||||
$markCount = 0;
|
||||
|
||||
foreach ($posts as $post) {
|
||||
// 标记插件接口
|
||||
self::pluginHandle()->call('mark', $status, $post, $this);
|
||||
|
||||
$condition = $this->db->sql()->where('cid = ?', $post);
|
||||
$postObject = $this->db->fetchObject($this->db->select('status', 'type')
|
||||
->from('table.contents')->where('cid = ? AND (type = ? OR type = ?)', $post, 'post', 'post_draft'));
|
||||
|
||||
if ($this->isWriteable(clone $condition) && count((array)$postObject)) {
|
||||
|
||||
/** 标记状态 */
|
||||
$this->db->query($condition->update('table.contents')->rows(['status' => $status]));
|
||||
|
||||
// 刷新Metas
|
||||
if ($postObject->type == 'post') {
|
||||
$op = null;
|
||||
|
||||
if ($status == 'publish' && $postObject->status != 'publish') {
|
||||
$op = '+';
|
||||
} elseif ($status != 'publish' && $postObject->status == 'publish') {
|
||||
$op = '-';
|
||||
}
|
||||
|
||||
if (!empty($op)) {
|
||||
$metas = $this->db->fetchAll(
|
||||
$this->db->select()->from('table.relationships')->where('cid = ?', $post)
|
||||
);
|
||||
foreach ($metas as $meta) {
|
||||
$this->db->query($this->db->update('table.metas')
|
||||
->expression('count', 'count ' . $op . ' 1')
|
||||
->where('mid = ? AND (type = ? OR type = ?)', $meta['mid'], 'category', 'tag'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理草稿
|
||||
$draft = $this->db->fetchRow($this->db->select('cid')
|
||||
->from('table.contents')
|
||||
->where('table.contents.parent = ? AND table.contents.type = ?', $post, 'revision')
|
||||
->limit(1));
|
||||
|
||||
if (!empty($draft)) {
|
||||
$this->db->query($this->db->update('table.contents')->rows(['status' => $status])
|
||||
->where('cid = ?', $draft['cid']));
|
||||
}
|
||||
|
||||
// 完成标记插件接口
|
||||
self::pluginHandle()->call('finishMark', $status, $post, $this);
|
||||
|
||||
$markCount++;
|
||||
}
|
||||
|
||||
unset($condition);
|
||||
}
|
||||
|
||||
/** 设置提示信息 */
|
||||
Notice::alloc()
|
||||
->set(
|
||||
$markCount > 0 ? _t('文章已经被标记为<strong>%s</strong>', $statusList[$status]) : _t('没有文章被标记'),
|
||||
$markCount > 0 ? 'success' : 'notice'
|
||||
);
|
||||
|
||||
/** 返回原网页 */
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文章
|
||||
*
|
||||
* @throws DbException
|
||||
*/
|
||||
public function deletePost()
|
||||
{
|
||||
$posts = $this->request->filter('int')->getArray('cid');
|
||||
$deleteCount = 0;
|
||||
|
||||
foreach ($posts as $post) {
|
||||
// 删除插件接口
|
||||
self::pluginHandle()->call('delete', $post, $this);
|
||||
|
||||
$condition = $this->db->sql()->where('cid = ?', $post);
|
||||
$postObject = $this->db->fetchObject($this->db->select('status', 'type')
|
||||
->from('table.contents')->where('cid = ? AND (type = ? OR type = ?)', $post, 'post', 'post_draft'));
|
||||
|
||||
if ($this->isWriteable(clone $condition) && count((array)$postObject) && $this->delete($condition)) {
|
||||
|
||||
/** 删除分类 */
|
||||
$this->setCategories($post, [], 'publish' == $postObject->status
|
||||
&& 'post' == $postObject->type);
|
||||
|
||||
/** 删除标签 */
|
||||
$this->setTags($post, null, 'publish' == $postObject->status
|
||||
&& 'post' == $postObject->type);
|
||||
|
||||
/** 删除评论 */
|
||||
$this->db->query($this->db->delete('table.comments')
|
||||
->where('cid = ?', $post));
|
||||
|
||||
/** 解除附件关联 */
|
||||
$this->unAttach($post);
|
||||
|
||||
/** 删除草稿 */
|
||||
$draft = $this->db->fetchRow($this->db->select('cid')
|
||||
->from('table.contents')
|
||||
->where('table.contents.parent = ? AND table.contents.type = ?', $post, 'revision')
|
||||
->limit(1));
|
||||
|
||||
/** 删除自定义字段 */
|
||||
$this->deleteFields($post);
|
||||
|
||||
if ($draft) {
|
||||
$this->deleteContent($draft['cid']);
|
||||
$this->deleteFields($draft['cid']);
|
||||
}
|
||||
|
||||
// 完成删除插件接口
|
||||
self::pluginHandle()->call('finishDelete', $post, $this);
|
||||
|
||||
$deleteCount++;
|
||||
}
|
||||
|
||||
unset($condition);
|
||||
}
|
||||
|
||||
// 清理标签
|
||||
if ($deleteCount > 0) {
|
||||
Metas::alloc()->clearTags();
|
||||
}
|
||||
|
||||
/** 设置提示信息 */
|
||||
Notice::alloc()->set(
|
||||
$deleteCount > 0 ? _t('文章已经被删除') : _t('没有文章被删除'),
|
||||
$deleteCount > 0 ? 'success' : 'notice'
|
||||
);
|
||||
|
||||
/** 返回原网页 */
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文章所属草稿
|
||||
*
|
||||
* @throws DbException
|
||||
*/
|
||||
public function deletePostDraft()
|
||||
{
|
||||
$posts = $this->request->filter('int')->getArray('cid');
|
||||
$deleteCount = 0;
|
||||
|
||||
foreach ($posts as $post) {
|
||||
/** 删除草稿 */
|
||||
$draft = $this->db->fetchRow($this->db->select('cid')
|
||||
->from('table.contents')
|
||||
->where('table.contents.parent = ? AND table.contents.type = ?', $post, 'revision')
|
||||
->limit(1));
|
||||
|
||||
if ($draft) {
|
||||
$this->deleteContent($draft['cid']);
|
||||
$this->deleteFields($draft['cid']);
|
||||
$deleteCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/** 设置提示信息 */
|
||||
Notice::alloc()
|
||||
->set(
|
||||
$deleteCount > 0 ? _t('草稿已经被删除') : _t('没有草稿被删除'),
|
||||
$deleteCount > 0 ? 'success' : 'notice'
|
||||
);
|
||||
|
||||
/** 返回原网页 */
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws DbException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function prepare(): self
|
||||
{
|
||||
return $this->prepareEdit('post', true, _t('文章不存在'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定动作
|
||||
*
|
||||
* @throws Exception|DbException
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
$this->security->protect();
|
||||
$this->on($this->request->is('do=publish') || $this->request->is('do=save'))
|
||||
->prepare()->writePost();
|
||||
$this->on($this->request->is('do=delete'))->deletePost();
|
||||
$this->on($this->request->is('do=mark'))->markPost();
|
||||
$this->on($this->request->is('do=deleteDraft'))->deletePostDraft();
|
||||
|
||||
$this->response->redirect($this->options->adminUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getThemeFieldsHook(): string
|
||||
{
|
||||
return 'themePostFields';
|
||||
}
|
||||
}
|
||||
54
var/Widget/Contents/Post/Recent.php
Executable file
54
var/Widget/Contents/Post/Recent.php
Executable file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Widget\Contents\Post;
|
||||
|
||||
use Typecho\Db;
|
||||
use Widget\Base\Contents;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 最新评论组件
|
||||
*
|
||||
* @category typecho
|
||||
* @package Widget
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
*/
|
||||
class Recent extends Contents
|
||||
{
|
||||
/**
|
||||
* 执行函数
|
||||
*
|
||||
* @throws Db\Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->parameter->setDefault(['pageSize' => $this->options->postsListSize]);
|
||||
|
||||
$this->db->fetchAll($this->select(
|
||||
'table.contents.cid',
|
||||
'table.contents.title',
|
||||
'table.contents.slug',
|
||||
'table.contents.created',
|
||||
'table.contents.modified',
|
||||
'table.contents.type',
|
||||
'table.contents.status',
|
||||
'table.contents.commentsNum',
|
||||
'table.contents.allowComment',
|
||||
'table.contents.allowPing',
|
||||
'table.contents.allowFeed',
|
||||
'table.contents.template',
|
||||
'table.contents.password',
|
||||
'table.contents.authorId',
|
||||
'table.contents.parent',
|
||||
)
|
||||
->where('table.contents.status = ?', 'publish')
|
||||
->where('table.contents.created < ?', $this->options->time)
|
||||
->where('table.contents.type = ?', 'post')
|
||||
->order('table.contents.created', Db::SORT_DESC)
|
||||
->limit($this->parameter->pageSize), [$this, 'push']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user