* Add feed widget * add feed render * Add CommentPage widget * New theme (#1390) * 调整忽略目录 * add theme * fix theme scss build Co-authored-by: fen <f3nb0x@gmail.com> * s/is_writeable/is_writable/g * New upgrade method * merge new fixes from master * add pgsql ssl mode support (ref #1600) (#1623) * Feat/code refactor (#1626) * remove all magic methods, add type for class properties * refactor codes * fix all * refactor code * fix type * fix all * fix request is method * fix all * fix router * fix get page * fix 1.3.0 upgrade * [feat] support high resolution avatar * fix types in i18n component * Implement Ctrl+S or Command+S for save draft (#1628) * Implement Ctrl+S or Command+S for save draft * rename * add Typecho.savePost * fix upload file size * add new uploader * replace new uploader * fix textarea change * fix preview * refactor post edit * fix issue * fix page edit --------- Co-authored-by: joyqi <joyqi@segmentfault.com> Co-authored-by: joyqi <magike.net@gmail.com> * fix #1632 * Add svg to image types * Feat/tree pages (#1646) * add tree trait * finish category tree trait * support select fields * fix select fields * refactor admin trait * fix draft status * Add new contents type "revision" * minor refactor * add more tree view abstracts * add tree trait to pages * get ready for tree view pages * improve page edit * fix revision * fix slug * add router params delegate * fix params delegate * fix * fix * fix all * fix all * fix tree * fix page link * fix feed * fix page * fix permalink * fix permalink input * fix offset query * Support IDN (#1629) * Support IDN * use js * Optimize code * Optimize code * fix URL script * remove unnecessary use --------- Co-authored-by: joyqi <joyqi@segmentfault.com> * fix input element * fix #1651, close #1653 * Use json instead of serialize (#1624) * Use json instead of serialize * Fix Upgrade code * add tree trait * finish category tree trait * support select fields * fix select fields * refactor admin trait * fix draft status * Add new contents type "revision" * minor refactor * add more tree view abstracts * add tree trait to pages * get ready for tree view pages * improve page edit * fix revision * fix slug * add router params delegate * fix params delegate * fix * fix * fix all * fix all * fix tree * fix page link * fix feed * fix page * fix permalink * fix permalink input * fix offset query * Fix typo * remove proxy methods * remove unnecessary useage --------- Co-authored-by: joyqi <joyqi@segmentfault.com> Co-authored-by: joyqi <magike.net@gmail.com> * Fix Prevent XSS vulnerability in default theme (#1654) * Fix Prevent XSS vulnerability in default theme * Update var/Typecho/Db/Adapter/Pdo.php * fix the getter --------- Co-authored-by: joyqi <joyqi@segmentfault.com> * add throwCallback to widget response * fix: cut down fields when selecting recent posts * fix typo errors * fix typo errors * fix http client cookie * add throw finish * fix theme lang * fix default theme * fix query * add open graph and twitter card support add canonical link * fix canonical link meta * fix theme classic-22 * remove unnecessary scss file when packaging * init plugin signal * improve: remove feather-icon js file * fix: typo * improve: post detail layout * fix tags saving * improve: nav search * fix: theme screenshot * fix: theme page layout * remove php 7.2/7.3 env --------- Co-authored-by: fen <f3nb0x@gmail.com> Co-authored-by: Lu Fei <52o@qq52o.cn>
213 lines
6.7 KiB
PHP
213 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace Widget;
|
|
|
|
use Exception;
|
|
use Typecho\Common;
|
|
use Typecho\Config;
|
|
use Typecho\Router;
|
|
use Typecho\Widget\Exception as WidgetException;
|
|
use Widget\Base\Contents;
|
|
use Typecho\Feed as FeedGenerator;
|
|
use Widget\Comments\Recent;
|
|
|
|
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Feed handler
|
|
*/
|
|
class Feed extends Contents
|
|
{
|
|
/**
|
|
* @var FeedGenerator
|
|
*/
|
|
private FeedGenerator $feed;
|
|
|
|
/**
|
|
* @param Config $parameter
|
|
* @throws Exception
|
|
*/
|
|
protected function initParameter(Config $parameter)
|
|
{
|
|
$parameter->setDefault([
|
|
'pageSize' => 10,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function execute()
|
|
{
|
|
$feedPath = $this->request->get('feed');
|
|
$feedType = FeedGenerator::RSS2;
|
|
$feedContentType = 'application/rss+xml';
|
|
$currentFeedUrl = $this->options->feedUrl;
|
|
$isComments = false;
|
|
|
|
/** 判断聚合类型 */
|
|
switch (true) {
|
|
case preg_match("/^\/rss(\/|$)/", $feedPath):
|
|
/** 如果是RSS1标准 */
|
|
$feedPath = substr($feedPath, 4);
|
|
$feedType = FeedGenerator::RSS1;
|
|
$currentFeedUrl = $this->options->feedRssUrl;
|
|
$feedContentType = 'application/rdf+xml';
|
|
break;
|
|
case preg_match("/^\/atom(\/|$)/", $feedPath):
|
|
/** 如果是ATOM标准 */
|
|
$feedPath = substr($feedPath, 5);
|
|
$feedType = FeedGenerator::ATOM1;
|
|
$currentFeedUrl = $this->options->feedAtomUrl;
|
|
$feedContentType = 'application/atom+xml';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
$feed = new FeedGenerator(
|
|
Common::VERSION,
|
|
$feedType,
|
|
$this->options->charset,
|
|
_t('zh-CN')
|
|
);
|
|
|
|
if (preg_match("/^\/comments\/?$/", $feedPath)) {
|
|
$isComments = true;
|
|
$currentFeedUrl = Common::url('/comments/', $currentFeedUrl);
|
|
$feed->setBaseUrl($this->options->siteUrl);
|
|
$feed->setSubTitle($this->options->description);
|
|
} else {
|
|
$archive = Router::match($feedPath, [
|
|
'pageSize' => $this->parameter->pageSize,
|
|
'isFeed' => true
|
|
]);
|
|
|
|
if (!($archive instanceof Archive)) {
|
|
throw new WidgetException(_t('聚合页不存在'), 404);
|
|
}
|
|
|
|
switch ($feedType) {
|
|
case FeedGenerator::RSS1:
|
|
$currentFeedUrl = $archive->getArchiveFeedRssUrl();
|
|
break;
|
|
case FeedGenerator::ATOM1:
|
|
$currentFeedUrl = $archive->getArchiveFeedAtomUrl();
|
|
break;
|
|
default:
|
|
$currentFeedUrl = $archive->getArchiveFeedUrl();
|
|
break;
|
|
}
|
|
|
|
$feed->setBaseUrl($archive->getArchiveUrl());
|
|
$feed->setSubTitle($archive->getArchiveDescription());
|
|
}
|
|
|
|
$this->checkPermalink($currentFeedUrl);
|
|
$feed->setFeedUrl($currentFeedUrl);
|
|
$this->feed($feed, $feedContentType, $isComments, $archive ?? null);
|
|
$this->feed = $feed;
|
|
}
|
|
|
|
/**
|
|
* @param FeedGenerator $feed
|
|
* @param string $contentType
|
|
* @param bool $isComments
|
|
* @param Archive|null $archive
|
|
*/
|
|
public function feed(
|
|
FeedGenerator $feed,
|
|
string $contentType,
|
|
bool $isComments,
|
|
?Archive $archive
|
|
) {
|
|
if ($isComments || $archive->is('single')) {
|
|
$feed->setTitle(_t(
|
|
'%s 的评论',
|
|
$this->options->title . ($isComments ? '' : ' - ' . $archive->getArchiveTitle())
|
|
));
|
|
|
|
if ($isComments) {
|
|
$comments = Recent::alloc('pageSize=10');
|
|
} else {
|
|
$comments = Recent::alloc('pageSize=10&parentId=' . $archive->cid);
|
|
}
|
|
|
|
while ($comments->next()) {
|
|
$suffix = self::pluginHandle()->trigger($plugged)->call(
|
|
'commentFeedItem',
|
|
$feed->getType(),
|
|
$comments
|
|
);
|
|
|
|
if (!$plugged) {
|
|
$suffix = null;
|
|
}
|
|
|
|
$feed->addItem([
|
|
'title' => $comments->author,
|
|
'content' => $comments->content,
|
|
'date' => $comments->created,
|
|
'link' => $comments->permalink,
|
|
'author' => (object)[
|
|
'screenName' => $comments->author,
|
|
'url' => $comments->url,
|
|
'mail' => $comments->mail
|
|
],
|
|
'excerpt' => strip_tags($comments->content),
|
|
'suffix' => $suffix
|
|
]);
|
|
}
|
|
} else {
|
|
$feed->setTitle($this->options->title
|
|
. ($archive->getArchiveTitle() ? ' - ' . $archive->getArchiveTitle() : ''));
|
|
|
|
while ($archive->next()) {
|
|
$suffix = self::pluginHandle()->trigger($plugged)->call('feedItem', $feed->getType(), $archive);
|
|
|
|
if (!$plugged) {
|
|
$suffix = null;
|
|
}
|
|
|
|
$feed->addItem([
|
|
'title' => $archive->title,
|
|
'content' => $this->options->feedFullText ? $archive->content
|
|
: (false !== strpos($archive->text, '<!--more-->') ? $archive->excerpt .
|
|
"<p class=\"more\"><a href=\"{$archive->permalink}\" title=\"{$archive->title}\">[...]</a></p>"
|
|
: $archive->content),
|
|
'date' => $archive->created,
|
|
'link' => $archive->permalink,
|
|
'author' => $archive->author,
|
|
'excerpt' => $archive->plainExcerpt,
|
|
'category' => $archive->categories->toArray(['name', 'permalink']),
|
|
'comments' => $archive->commentsNum,
|
|
'commentsFeedUrl' => Common::url($archive->path, $feed->getFeedUrl()),
|
|
'suffix' => $suffix
|
|
]);
|
|
}
|
|
}
|
|
|
|
$this->response->setContentType($contentType);
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function render()
|
|
{
|
|
echo $this->feed;
|
|
}
|
|
|
|
/**
|
|
* @param string $feedUrl
|
|
*/
|
|
private function checkPermalink(string $feedUrl)
|
|
{
|
|
if ($feedUrl != $this->request->getRequestUrl()) {
|
|
$this->response->redirect($feedUrl, true);
|
|
}
|
|
}
|
|
}
|