/** * 执行函数,初始化数据 * * @access public * @return void */ public function execute() { $this->parameter->setDefault('limit=5'); if ($this->parameter->tags) { $tagsGroup = implode(',', Typecho_Common::arrayFlatten($this->parameter->tags, 'mid')); $this->db->fetchAll($this->select()->join('table.relationships', 'table.contents.cid = table.relationships.cid')->where('table.relationships.mid IN (' . $tagsGroup . ')')->where('table.contents.cid <> ?', $this->parameter->cid)->where('table.contents.status = ?', 'publish')->where('table.contents.password IS NULL')->where('table.contents.created < ?', $this->options->gmtTime)->where('table.contents.type = ?', $this->parameter->type)->order('table.contents.created', Typecho_Db::SORT_DESC)->limit($this->parameter->limit), array($this, 'push')); } }
function OutputArchives($db, $options) { $select = $db->select('cid', 'title', 'slug', 'created', 'allowComment', 'commentsNum')->from('table.contents')->where('status = ?', 'publish')->where('type = ?', 'post'); $rawposts = $db->fetchAll($select); $posts = array(); // Loop through each post and sort it into a structured array foreach ($rawposts as $post) { /** 取出所有分类 */ $categories = $isTypechoEX ? Cache_Plugin::meta_get($post['cid'], "category") : $db->fetchAll($db->select('slug')->from('table.metas')->join('table.relationships', 'table.metas.mid = table.relationships.mid')->where('table.relationships.cid = ?', $post['cid'])->where('table.metas.type = ?', 'category')->order('table.metas.order', Typecho_Db::SORT_ASC)); /** 取出第一个分类作为slug条件 */ $post['category'] = current(Typecho_Common::arrayFlatten($categories, 'slug')); $date = new Typecho_Date($post['created']); $post['year'] = $date->year; $post['month'] = $date->month; $post['day'] = $date->day; $type = 'post'; //$p['type']; $routeExists = NULL != Typecho_Router::get($type); $permalink = $routeExists ? Typecho_Router::url($type, $post, $options->index) : '#'; $post['permalink'] = $permalink; $posts[$post['year'] . '.' . $post['month']][] = $post; } $rawposts = null; // More memory cleanup // Sort the months based on $atts krsort($posts); // Sort the posts within each month based on $atts foreach ($posts as $key => $month) { $sorter = array(); foreach ($month as $post) { $sorter[] = $post['created']; } array_multisort($sorter, SORT_DESC, $month); $posts[$key] = $month; unset($month); } // Generate the HTML $html = ""; foreach ($posts as $yearmonth => $posts) { list($year, $month) = explode('.', $yearmonth); $html .= "<li><b><a href=\"" . Typecho_Router::url('archive_month', array('year' => $year, 'month' => $month), $options->index) . "\">" . $year . "年" . $month . "月</a></b> <span>(" . number_format(count($posts)) . " 篇文章)</span><ul>"; foreach ($posts as $post) { $html .= "<li>" . $post['day'] . ": <a href=\"" . $post['permalink'] . "\">" . $post['title'] . "</a> <span>(" . number_format($post['commentsNum']) . ")</span></li>"; } $html .= "</ul></li>"; } return $html; }
/** * 通用过滤器 * * @access public * @param array $value 需要过滤的行数据 * @return array */ public function filter(array $value) { /** 取出所有分类 */ $value['categories'] = $this->db->fetchAll($this->db->select()->from('table.metas')->join('table.relationships', 'table.relationships.mid = table.metas.mid')->where('table.relationships.cid = ?', $value['cid'])->where('table.metas.type = ?', 'category')->order('table.metas.order', Typecho_Db::SORT_ASC), array($this->widget('Widget_Abstract_Metas'), 'filter')); /** 取出第一个分类作为slug条件 */ $value['category'] = current(Typecho_Common::arrayFlatten($value['categories'], 'slug')); $value['date'] = new Typecho_Date($value['created']); /** 生成日期 */ $value['year'] = $value['date']->year; $value['month'] = $value['date']->month; $value['day'] = $value['date']->day; /** 生成访问权限 */ $value['hidden'] = false; /** 获取路由类型并判断此类型在路由表中是否存在 */ $type = $value['type']; $routeExists = NULL != Typecho_Router::get($type); $tmpSlug = $value['slug']; $tmpCategory = $value['category']; $value['slug'] = urlencode($value['slug']); $value['category'] = urlencode($value['category']); /** 生成静态路径 */ $value['pathinfo'] = $routeExists ? Typecho_Router::url($type, $value) : '#'; /** 生成静态链接 */ $value['permalink'] = Typecho_Common::url($value['pathinfo'], $this->options->index); /** 处理附件 */ if ('attachment' == $type) { $content = @unserialize($value['text']); //增加数据信息 $value['attachment'] = new Typecho_Config($content); $value['attachment']->isImage = in_array($content['type'], array('jpg', 'jpeg', 'gif', 'png', 'tiff', 'bmp')); $value['attachment']->url = Widget_Upload::attachmentHandle($value); if ($value['attachment']->isImage) { $value['text'] = '<img src="' . $value['attachment']->url . '" alt="' . $value['title'] . '" />'; } else { $value['text'] = '<a href="' . $value['attachment']->url . '" title="' . $value['title'] . '">' . $value['title'] . '</a>'; } } /** 处理Markdown **/ $value['isMarkdown'] = 0 === strpos($value['text'], '<!--markdown-->'); if ($value['isMarkdown']) { $value['text'] = substr($value['text'], 15); } /** 生成聚合链接 */ /** RSS 2.0 */ $value['feedUrl'] = $routeExists ? Typecho_Router::url($type, $value, $this->options->feedUrl) : '#'; /** RSS 1.0 */ $value['feedRssUrl'] = $routeExists ? Typecho_Router::url($type, $value, $this->options->feedRssUrl) : '#'; /** ATOM 1.0 */ $value['feedAtomUrl'] = $routeExists ? Typecho_Router::url($type, $value, $this->options->feedAtomUrl) : '#'; $value['slug'] = $tmpSlug; $value['category'] = $tmpCategory; /** 处理密码保护流程 */ if (!empty($value['password']) && $value['password'] != $this->request->protectPassword && $value['authorId'] != $this->user->uid && !$this->user->pass('editor', true)) { $value['hidden'] = true; /** 抛出错误 */ if ($this->request->isPost() && isset($this->request->protectPassword)) { throw new Typecho_Widget_Exception(_t('对不起,您输入的密码错误'), 403); } } $value = $this->pluginHandle(__CLASS__)->filter($value, $this); /** 如果访问权限被禁止 */ if ($value['hidden']) { $value['text'] = '<form class="protected" action="' . $value['permalink'] . '" method="post">' . '<p class="word">' . _t('请输入密码访问') . '</p>' . '<p><input type="password" class="text" name="protectPassword" /> <input type="submit" class="submit" value="' . _t('提交') . '" /></p>' . '</form>'; $value['title'] = _t('此内容被密码保护'); $value['tags'] = array(); $value['commentsNum'] = 0; } return $value; }
/** * 清理没有任何内容的标签 * * @access public * @return void */ public function clearTags() { // 取出count为0的标签 $tags = Typecho_Common::arrayFlatten($this->db->fetchAll($this->db->select('mid')->from('table.metas')->where('type = ? AND count = ?', 'tags', 0)), 'mid'); foreach ($tags as $tag) { // 确认是否已经没有关联了 $content = $this->db->fetchRow($this->db->select('cid')->from('table.relationships')->where('mid = ?', $tag)->limit(1)); if (empty($content)) { $this->db->query($this->db->delete('table.metas')->where('mid = ?', $tag)); } } }
/** * 获取当前作者前postsNum个post * * @param int $blogId * @param string $userName * @param string $password * @param int $postsNum * @access public * @return void */ public function bloggerGetRecentPosts($blogId, $userName, $password, $postsNum) { if (!$this->checkAccess($userName, $password)) { return $this->error; } //todo:限制数量 $posts = $this->singletonWidget('Widget_Contents_Post_Admin', "pageSize={$postsNum}", 'status=all'); $postStructs = array(); while ($posts->next()) { $categories = Typecho_Common::arrayFlatten($posts->categories, 'name'); $content = '<title>' . $posts->title . '</title>'; $content .= '<category>' . implode(',', $categories) . '</category>'; $content .= stripslashes($posts->text); $struct = array('userid' => $posts->authorId, 'dateCreated' => new IXR_Date($this->options->timezone + $posts->created), 'content' => $content, 'postid' => $posts->cid); $postStructs[] = $struct; } if (NULL == $postStructs) { return new IXR_Error('404', '没有任何文章'); } return $postStructs; }
/** * 保存自定义字段 * * @param array $fields * @param mixed $cid * @access public * @return void */ public function applyFields(array $fields, $cid) { $exists = array_flip(Typecho_Common::arrayFlatten($this->db->fetchAll($this->db->select('name')->from('table.fields')->where('cid = ?', $cid)), 'name')); foreach ($fields as $name => $value) { $type = 'str'; if (is_array($value) && 2 == count($value)) { $type = $value[0]; $value = $value[1]; } else { if (strpos($name, ':') > 0) { list($type, $name) = explode(':', $name, 2); } } if (!$this->checkFieldName($name)) { continue; } $isFieldReadOnly = $this->pluginHandle(__CLASS__)->trigger($plugged)->isFieldReadOnly($name); if ($plugged && $isFieldReadOnly) { continue; } if (isset($exists[$name])) { unset($exists[$name]); } $this->setField($name, $type, $value, $cid); } foreach ($exists as $name => $value) { $this->db->query($this->db->delete('table.fields')->where('cid = ? AND name = ?', $cid, $name)); } }
?> " /></p> </section> <section class="typecho-post-option category-option"> <label class="typecho-label"><?php _e('分类'); ?> </label> <?php Typecho_Widget::widget('Widget_Metas_Category_List')->to($category); ?> <ul> <?php if ($post->have()) { $categories = Typecho_Common::arrayFlatten($post->categories, 'mid'); } else { $categories = array(); } ?> <?php while ($category->next()) { ?> <li><?php echo str_repeat(' ', $category->levels); ?> <input type="checkbox" id="category-<?php $category->mid(); ?> " value="<?php $category->mid();
/** * 准备数据 * @param $contents 文章内容 * @param $class 调用接口的类 * @throws Typecho_Plugin_Exception */ public static function send($contents, $class) { //如果文章属性为隐藏或滞后发布 if ('publish' != $contents['visibility'] || $contents['created'] > time()) { return; } //获取系统配置 $options = Helper::options(); //判断是否配置好API if (is_null($options->plugin('BaiduSubmit')->api)) { throw new Typecho_Plugin_Exception(_t('api未配置')); } //获取文章类型 $type = $contents['type']; //获取路由信息 $routeExists = NULL != Typecho_Router::get($type); if (!is_null($routeExists)) { $db = Typecho_Db::get(); $contents['cid'] = $class->cid; $contents['categories'] = $db->fetchAll($db->select()->from('table.metas')->join('table.relationships', 'table.relationships.mid = table.metas.mid')->where('table.relationships.cid = ?', $contents['cid'])->where('table.metas.type = ?', 'category')->order('table.metas.order', Typecho_Db::SORT_ASC)); $contents['category'] = urlencode(current(Typecho_Common::arrayFlatten($contents['categories'], 'slug'))); $contents['slug'] = urlencode($contents['slug']); $contents['date'] = new Typecho_Date($contents['created']); $contents['year'] = $contents['date']->year; $contents['month'] = $contents['date']->month; $contents['day'] = $contents['date']->day; } //生成永久连接 $path_info = $routeExists ? Typecho_Router::url($type, $contents) : '#'; $permalink = Typecho_Common::url($path_info, $options->index); //调用post方法 self::post($permalink); }
/** * 设置分类 * * @access protected * @param integer $cid 内容id * @param array $categories 分类id的集合数组 * @param boolean $count 是否参与计数 * @return integer */ protected function setCategories($cid, array $categories, $beforeCount = true, $afterCount = true) { $categories = array_unique(array_map('trim', $categories)); /** 取出已有category */ $existCategories = Typecho_Common::arrayFlatten($this->db->fetchAll($this->db->select('table.metas.mid')->from('table.metas')->join('table.relationships', 'table.relationships.mid = table.metas.mid')->where('table.relationships.cid = ?', $cid)->where('table.metas.type = ?', 'category')), 'mid'); /** 删除已有category */ if ($existCategories) { foreach ($existCategories as $category) { $this->db->query($this->db->delete('table.relationships')->where('cid = ?', $cid)->where('mid = ?', $category)); if ($beforeCount) { $this->db->query($this->db->update('table.metas')->expression('count', 'count - 1')->where('mid = ?', $category)); } } } /** 插入category */ if ($categories) { foreach ($categories as $category) { /** 如果分类不存在 */ if (!$this->db->fetchRow($this->db->select('mid')->from('table.metas')->where('mid = ?', $category)->limit(1))) { continue; } $this->db->query($this->db->insert('table.relationships')->rows(array('mid' => $category, 'cid' => $cid))); if ($afterCount) { $this->db->query($this->db->update('table.metas')->expression('count', 'count + 1')->where('mid = ?', $category)); } } } }
/** * 执行函数 * * @access public * @return void */ public function execute() { $select = $this->db->select('mid')->from('table.metas')->where('type = ?', 'category'); $select->where('parent = ?', $this->request->parent ? $this->request->parent : 0); $this->stack = $this->getCategories(Typecho_Common::arrayFlatten($this->db->fetchAll($select->order('table.metas.order', Typecho_Db::SORT_ASC)), 'mid')); }
/** * clearAttachment * * @access public * @return void */ public function clearAttachment() { $page = 1; $deleteCount = 0; do { $posts = Typecho_Common::arrayFlatten($this->db->fetchAll($this->select('cid')->from('table.contents')->where('type = ? AND parent = ?', 'attachment', 0)->page($page, 100)), 'cid'); $page++; foreach ($posts as $post) { // 删除插件接口 $this->pluginHandle()->delete($post, $this); $condition = $this->db->sql()->where('cid = ?', $post); $row = $this->db->fetchRow($this->select()->where('table.contents.type = ?', 'attachment')->where('table.contents.cid = ?', $post)->limit(1), array($this, 'push')); if ($this->isWriteable($condition) && $this->delete($condition)) { /** 删除文件 */ Widget_Upload::deleteHandle($row); /** 删除评论 */ $this->db->query($this->db->delete('table.comments')->where('cid = ?', $post)); $status = $this->status; // 完成删除插件接口 $this->pluginHandle()->finishDelete($post, $this); $deleteCount++; } unset($condition); } } while (count($posts) == 100); /** 设置提示信息 */ $this->widget('Widget_Notice')->set($deleteCount > 0 ? _t('未归档文件已经被清理') : _t('没有未归档文件被清理'), $deleteCount > 0 ? 'success' : 'notice'); /** 返回原网页 */ $this->response->redirect(Typecho_Common::url('manage-medias.php', $this->options->adminUrl)); }
/** * 独立页处理 * * @access private * @param Typecho_Db_Query $select 查询对象 * @param boolean $hasPushed 是否已经压入队列 * @return void * @throws Typecho_Widget_Exception */ private function singleHandle(Typecho_Db_Query $select, &$hasPushed) { if ('comment_page' == $this->parameter->type) { $params = array(); $matched = Typecho_Router::match($this->request->permalink); if ($matched && $matched instanceof Widget_Archive && $matched->is('single')) { $this->import($matched); $hasPushed = true; return; } } /** 将这两个设置提前是为了保证在调用query的plugin时可以在插件中使用is判断初步归档类型 */ /** 如果需要更细判断,则可以使用singleHandle来实现 */ $this->_archiveSingle = true; /** 默认归档类型 */ $this->_archiveType = 'single'; /** 匹配类型 */ if ('single' != $this->parameter->type) { $select->where('table.contents.type = ?', $this->parameter->type); } /** 如果是单篇文章或独立页面 */ if (isset($this->request->cid)) { $select->where('table.contents.cid = ?', $this->request->filter('int')->cid); } /** 匹配缩略名 */ if (isset($this->request->slug)) { $select->where('table.contents.slug = ?', $this->request->slug); } /** 匹配时间 */ if (isset($this->request->year)) { $year = $this->request->filter('int')->year; $fromMonth = 1; $toMonth = 12; $fromDay = 1; $toDay = 31; if (isset($this->request->month)) { $fromMonth = $this->request->filter('int')->month; $toMonth = $fromMonth; $fromDay = 1; $toDay = date('t', mktime(0, 0, 0, $toMonth, 1, $year)); if (isset($this->request->day)) { $fromDay = $this->request->filter('int')->day; $toDay = $fromDay; } } /** 获取起始GMT时间的unix时间戳 */ $from = mktime(0, 0, 0, $fromMonth, $fromDay, $year) - $this->options->timezone + $this->options->serverTimezone; $to = mktime(23, 59, 59, $toMonth, $toDay, $year) - $this->options->timezone + $this->options->serverTimezone; $select->where('table.contents.created > ? AND table.contents.created < ?', $from, $to); } /** 保存密码至cookie */ if ($this->request->isPost() && isset($this->request->protectPassword)) { $this->security->protect(); Typecho_Cookie::set('protectPassword', $this->request->protectPassword, 0); } /** 匹配类型 */ $select->limit(1); $this->query($select); if (!$this->have() || isset($this->request->category) && $this->category != $this->request->category || isset($this->request->directory) && $this->request->directory != implode('/', $this->directory)) { if (!$this->_invokeFromOutside) { /** 对没有索引情况下的判断 */ throw new Typecho_Widget_Exception(_t('请求的地址不存在'), 404); } else { $hasPushed = true; return; } } /** 设置模板 */ if ($this->template) { /** 应用自定义模板 */ $this->_themeFile = $this->template; } /** 设置头部feed */ /** RSS 2.0 */ //对自定义首页使用全局变量 if (!$this->_makeSinglePageAsFrontPage) { $this->_feedUrl = $this->feedUrl; /** RSS 1.0 */ $this->_feedRssUrl = $this->feedRssUrl; /** ATOM 1.0 */ $this->_feedAtomUrl = $this->feedAtomUrl; /** 设置标题 */ $this->_archiveTitle = $this->title; /** 设置关键词 */ $this->_keywords = implode(',', Typecho_Common::arrayFlatten($this->tags, 'name')); /** 设置描述 */ $this->_description = $this->description; } /** 设置归档类型 */ $this->_archiveType = $this->type; /** 设置归档缩略名 */ $this->_archiveSlug = 'post' == $this->type || 'attachment' == $this->type ? $this->cid : $this->slug; /** 设置403头 */ if ($this->hidden) { $this->response->setStatus(403); } $hasPushed = true; /** 插件接口 */ $this->pluginHandle()->singleHandle($this, $select); }
/** * Grab all posts and filter them into an array * */ public static function GetPosts() { $options = Typecho_Widget::widget('Widget_Options'); /** * 获取数据库实例化对象 * 用静态变量存储实例化的数据库对象,可以保证数据连接仅进行一次 */ $db = Typecho_Db::get(); $select = $db->select('cid', 'title', 'slug', 'created', 'allowComment', 'commentsNum')->from('table.contents')->where('status = ?', 'publish')->where('type = ?', 'post'); $rawposts = $db->fetchAll($select); $posts = array(); // Loop through each post and sort it into a structured array foreach ($rawposts as $post) { /** 取出所有分类 */ $categories = $db->fetchAll($db->select('slug')->from('table.metas')->join('table.relationships', 'table.metas.mid = table.relationships.mid')->where('table.relationships.cid = ?', $post['cid'])->where('table.metas.type = ?', 'category')->order('table.metas.order', Typecho_Db::SORT_ASC)); /** 取出第一个分类作为slug条件 */ $post['category'] = current(Typecho_Common::arrayFlatten($categories, 'slug')); $date = new Typecho_Date($post['created']); $post['year'] = $date->year; $post['month'] = $date->month; $post['day'] = $date->day; $type = 'post'; //$p['type']; $routeExists = NULL != Typecho_Router::get($type); $permalink = $routeExists ? Typecho_Router::url($type, $post, $options->index) : '#'; $post['permalink'] = $permalink; $posts[$post['year'] . '.' . $post['month']][] = $post; } $rawposts = null; // More memory cleanup return $posts; }
/** * 编辑文章后更新缓存 * @param $contents * @param $class */ public static function post_update($contents, $class) { if ('publish' != $contents['visibility'] || $contents['created'] > time()) { return; } //获取系统配置 $options = Helper::options(); if (!$options->plugin('TpCache')->cache_driver) { return; } //获取文章类型 $type = $contents['type']; //获取路由信息 $routeExists = NULL != Typecho_Router::get($type); if (!is_null($routeExists)) { $db = Typecho_Db::get(); $contents['cid'] = $class->cid; $contents['categories'] = $db->fetchAll($db->select()->from('table.metas')->join('table.relationships', 'table.relationships.mid = table.metas.mid')->where('table.relationships.cid = ?', $contents['cid'])->where('table.metas.type = ?', 'category')->order('table.metas.order', Typecho_Db::SORT_ASC)); $contents['category'] = urlencode(current(Typecho_Common::arrayFlatten($contents['categories'], 'slug'))); $contents['slug'] = urlencode($contents['slug']); $contents['date'] = new Typecho_Date($contents['created']); $contents['year'] = $contents['date']->year; $contents['month'] = $contents['date']->month; $contents['day'] = $contents['date']->day; } //生成永久连接 $path_info = $routeExists ? Typecho_Router::url($type, $contents) : '#'; self::init(); if (self::needCache($path_info)) { self::delete(self::$path); } }
/** * 合并数据 * * @access public * @param integer $mid 数据主键 * @param string $type 数据类型 * @param array $metas 需要合并的数据集 * @return void */ public function merge($mid, $type, array $metas) { $contents = Typecho_Common::arrayFlatten($this->db->fetchAll($this->select('cid')->from('table.relationships')->where('mid = ?', $mid)), 'cid'); foreach ($metas as $meta) { if ($mid != $meta) { $existsContents = Typecho_Common::arrayFlatten($this->db->fetchAll($this->db->select('cid')->from('table.relationships')->where('mid = ?', $meta)), 'cid'); $where = $this->db->sql()->where('mid = ? AND type = ?', $meta, $type); $this->delete($where); $diffContents = array_diff($existsContents, $contents); $this->db->query($this->db->delete('table.relationships')->where('mid = ?', $meta)); foreach ($diffContents as $content) { $this->db->query($this->db->insert('table.relationships')->rows(array('mid' => $mid, 'cid' => $content))); $contents[] = $content; } unset($existsContents); } } $num = $this->db->fetchObject($this->db->select(array('COUNT(mid)' => 'num'))->from('table.relationships')->where('table.relationships.mid = ?', $mid))->num; $this->update(array('count' => $num), $this->db->sql()->where('mid = ?', $mid)); }