one class per file

master
Jean-Christian Paul Denis 2022-12-10 22:20:42 +01:00
parent 2bf914de7e
commit 098c5338e3
Signed by: JcDenis
GPG Key ID: 1B5B8C5B90B6C951
16 changed files with 1771 additions and 1347 deletions

View File

@ -55,227 +55,3 @@ if (dcCore::app()->blog->settings->__get(basename(__DIR__))->zoneclearFeedServer
# Delete related info about feed post in meta table # Delete related info about feed post in meta table
dcCore::app()->addBehavior('adminBeforePostDelete', ['zcfsAdminBehaviors', 'adminBeforePostDelete']); dcCore::app()->addBehavior('adminBeforePostDelete', ['zcfsAdminBehaviors', 'adminBeforePostDelete']);
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - admin methods.
* @since 2.6
*/
class zcfsAdminBehaviors
{
public static function feedsSortbyCombo()
{
return [
__('Date') => 'feed_upddt',
__('Name') => 'lowername',
__('Frequency') => 'feed_upd_int',
__('Update date') => 'feed_upd_last',
__('Status') => 'feed_status',
];
}
public static function entriesSortbyCombo()
{
return [
__('Date') => 'post_dt',
__('Title') => 'post_title',
__('Category') => 'cat_title',
__('Author') => 'user_id',
__('Status') => 'post_status',
];
}
/**
* Favorites.
*
* @param dcFavorites $favs Array of favorites
*/
public static function adminDashboardFavoritesV2(dcFavorites $favs)
{
$favs->register('zcfs', [
'title' => __('Feeds server'),
'url' => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)),
'small-icon' => dcPage::getPF(basename(__DIR__) . '/icon.svg'),
'large-icon' => dcPage::getPF(basename(__DIR__) . '/icon.svg'),
'permissions' => dcCore::app()->auth->makePermissions([
dcAuth::PERMISSION_USAGE,
dcAuth::PERMISSION_CONTENT_ADMIN,
]),
'dashboard_cb' => ['zcfsAdminBehaviors', 'adminDashboardFavoritesCallback'],
]);
}
/**
* Favorites hack.
*
* @param arrayObject $fav Fav attributes
*/
public static function adminDashboardFavoritesCallback($fav)
{
$zcfs = new zoneclearFeedServer();
$count = $zcfs->getFeeds(['feed_status' => '0'], true)->f(0);
if (!$count) {
return null;
}
$fav['title'] .= '<br />' . sprintf(__('%s feed disabled', '%s feeds disabled', $count), $count);
$fav['large-icon'] = dcPage::getPF(basename(__DIR__) . '/icon-update.svg');
$fav['url'] = dcCore::app()->adminurl->get(
'admin.plugin.' . basename(__DIR__),
['part' => 'feeds', 'sortby' => 'feed_status', 'order' => 'asc']
);
}
/**
* User pref columns lists.
*
* @param arrayObject $cols Columns
*/
public static function adminColumnsListsV2($cols)
{
$cols['zcfs_feeds'] = [
__('Feeds server: Feeds'),
[
'desc' => [true, __('Feed')],
'period' => [true, __('Frequency')],
'update' => [true, __('Last update')],
'entries' => [true, __('Entries')],
],
];
$cols['zcfs_entries'] = [
__('Feeds server: Entries'),
[
'date' => [true, __('Date')],
'category' => [true, __('Category')],
'author' => [true, __('Author')],
],
];
}
/**
* User pref filters options.
*
* @param arrayObject $sorts Sort options
*/
public static function adminFiltersListsV2($sorts)
{
$sorts['zcfs_feeds'] = [
__('Feeds server: Feeds'),
self::feedsSortbyCombo(),
'lowername',
'asc',
[__('feeds per page'), 30],
];
$sorts['zcfs_entries'] = [
__('Feeds server: Entries'),
self::entriesSortbyCombo(),
'post_dt',
'desc',
[__('entries per page'), 30],
];
}
/**
* Add javascript for toggle to post edition page header.
*
* @return string Page header
*/
public static function adminPostHeaders()
{
return dcPage::jsLoad(dcPage::getPF(basename(__DIR__) . '/js/post.js'));
}
/**
* Add form to post sidebar.
*
* @param ArrayObject $main_items Main items
* @param ArrayObject $sidebar_items Sidebar items
* @param record $post Post record or null
*/
public static function adminPostFormItems(ArrayObject $main_items, ArrayObject $sidebar_items, $post)
{
if ($post === null || $post->post_type != 'post') {
return null;
}
$url = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_url',
'limit' => 1,
]);
$url = $url->isEmpty() ? '' : $url->meta_id;
if (!$url) {
return null;
}
$author = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_author',
'limit' => 1,
]);
$author = $author->isEmpty() ? '' : $author->meta_id;
$site = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_site',
'limit' => 1,
]);
$site = $site->isEmpty() ? '' : $site->meta_id;
$sitename = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_sitename',
'limit' => 1,
]);
$sitename = $sitename->isEmpty() ? '' : $sitename->meta_id;
$edit = '';
if (dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_CONTENT_ADMIN]), dcCore::app()->blog->id)) {
$fid = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_id',
'limit' => 1,
]);
if (!$fid->isEmpty()) {
$edit = sprintf(
'<p><a href="%s">%s</a></p>',
dcCore::app()->adminurl->get(
'admin.plugin.' . basename(__DIR__),
['part' => 'feed', 'feed_id' => $fid->meta_id]
),
__('Edit this feed')
);
}
}
$sidebar_items['options-box']['items']['zcfs'] = '<div id="zcfs">' .
'<h5>' . __('Feed source') . '</h5>' .
'<p>' .
'<a href="' . $url . '" title="' . $author . ' - ' . $url . '">' . __('feed URL') . '</a> - ' .
'<a href="' . $site . '" title="' . $sitename . ' - ' . $site . '">' . __('site URL') . '</a>' .
'</p>' .
$edit .
'</div>';
}
/**
* Delete related info about feed post in meta table.
*
* @param integer $post_id Post id
*/
public static function adminBeforePostDelete($post_id)
{
dcCore::app()->con->execute(
'DELETE FROM ' . dcCore::app()->prefix . dcMeta::META_TABLE_NAME . ' ' .
'WHERE post_id = ' . ((int) $post_id) . ' ' .
'AND meta_type ' . dcCore::app()->con->in([
'zoneclearfeed_url',
'zoneclearfeed_author',
'zoneclearfeed_site',
'zoneclearfeed_sitename',
'zoneclearfeed_id',
]) . ' '
);
}
}

View File

@ -15,12 +15,18 @@ if (!defined('DC_RC_PATH')) {
} }
Clearbricks::lib()->autoload([ Clearbricks::lib()->autoload([
'zoneclearFeedServer' => __DIR__ . '/inc/class.zoneclear.feed.server.php', 'zoneclearFeedServer' => __DIR__ . '/inc/class.zoneclearfeedserver.php',
'zcfsFeedsList' => __DIR__ . '/inc/lib.zcfs.list.php', 'zcfsAdminBehaviors' => __DIR__ . '/inc/class.zcfsadminbehaviors.php',
'zcfsEntriesList' => __DIR__ . '/inc/lib.zcfs.list.php', 'zcfsPostFilter' => __DIR__ . '/inc/class.zcfspostfilter.php',
'adminZcfsPostFilter' => __DIR__ . '/inc/lib.zcfs.list.php', 'zcfsEntriesList' => __DIR__ . '/inc/class.zcfsentrieslist.php',
'zcfsFeedsActionsPage' => __DIR__ . '/inc/class.zcfs.feedsactions.php', 'zcfsFeedsList' => __DIR__ . '/inc/class.zcfsfeedslist.php',
'zcfsDefaultFeedsActions' => __DIR__ . '/inc/class.zcfs.feedsactions.php', 'zcfsFeedsActions' => __DIR__ . '/inc/class.zcfsfeedsactions.php',
'zcfsDefaultFeedsActions' => __DIR__ . '/inc/class.zcfsdefaultfeedsactions.php',
'zcfsTemplate' => __DIR__ . '/inc/class.zcfstemplate.php',
'zcfsPublicBehaviors' => __DIR__ . '/inc/class.zcfspublicbehaviors.php',
'zcfsRsExtPosts' => __DIR__ . '/inc/class.zcfsrsextposts.php',
'zcfsUrlHandler' => __DIR__ . '/inc/class.zcfsurlhandler.php',
'zcfsActivityReportBehaviors' => __DIR__ . '/inc/class.zcfsactivityreportbehaviors.php',
]); ]);
// public url for page of description of the flux // public url for page of description of the flux
@ -33,5 +39,5 @@ dcCore::app()->url->register(
// Add to report on plugin activityReport // Add to report on plugin activityReport
if (defined('ACTIVITY_REPORT_V2')) { if (defined('ACTIVITY_REPORT_V2')) {
require_once __DIR__ . '/inc/lib.zcfs.activityreport.php'; zcfsActivityReportBehaviors::init();
} }

View File

@ -73,641 +73,8 @@ foreach ($tpl_values as $v) {
dcCore::app()->tpl->addValue('zc' . $v, ['zcfsTemplate', $v]); dcCore::app()->tpl->addValue('zc' . $v, ['zcfsTemplate', $v]);
} }
/** dcCore::app()->addBehavior('publicBreadcrumb', function ($context, $separator) {
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - public methods.
* @since 2.6
*/
class zcfsPublicBehaviors
{
/**
* Remember others post extension.
*
* @param dcRecord $rs record instance
*/
public static function coreBlogGetPosts(dcRecord $rs)
{
$GLOBALS['beforeZcFeedRsExt'] = $rs->extensions();
$rs->extend('zcfsRsExtPosts');
}
/**
* Update feeds after contents.
*/
public static function publicAfterDocumentV2()
{
# Limit feeds update to home page et feed page
# Like publishScheduledEntries
if (!in_array(dcCore::app()->url->type, ['default', 'feed'])) {
return null;
}
self::publicDocument();
}
/**
* Generic behavior for before and after public content.
*/
public static function publicDocumentV2()
{
$zc = new zoneclearFeedServer();
$zc->checkFeedsUpdate();
return null;
}
/**
* Update feeds by an Ajax request (background).
*/
public static function publicHeadContent()
{
# Limit update to home page
if (dcCore::app()->url->type != 'default') {
return null;
}
$blog_url = html::escapeJS(
dcCore::app()->blog->url .
dcCore::app()->url->getBase('zoneclearFeedsPage') .
'/zcfsupd'
);
$blog_id = html::escapeJS(dcCore::app()->blog->id);
echo
"\n<!-- JS for zoneclearFeedServer --> \n" .
dcUtils::jsLoad(dcCore::app()->blog->url . dcCore::app()->url->getBase('zoneclearFeedsPage') . '/zcfsupd.js') .
"<script type=\"text/javascript\"> \n//<![CDATA[\n" .
' $(function(){if(!document.getElementById){return;} ' .
" $('body').zoneclearFeedServer({blog_url:'" .
$blog_url . "',blog_id:'" . $blog_id . "'}); " .
" })\n" .
"//]]>\n</script>\n";
}
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - rs methods.
* @since 2.6
*/
class zcfsRsExtPosts extends rsExtPost
{
public static function zc()
{
return new zoneclearFeedServer();
}
/**
* Get feed meta.
*
* @param dcRecord $rs record instance
* @param string $info Feed info key
* @return string Feed info value
*/
public static function zcFeed($rs, $info)
{
$meta = dcCore::app()->meta->getMetadata([
'post_id' => $rs->post_id,
'meta_type' => 'zoneclearfeed_' . $info,
'limit' => 1,
]);
return $meta->isEmpty() ? null : $meta->meta_id;
}
/**
* Call other rs extension.
*
* @param string $type Type of extension
* @param array $args Arguments
* @return mixed record extension ressource
*/
public static function zcFeedBrother($type, $args)
{
if (!empty($GLOBALS['beforeZcFeedRsExt'][$type])) {
$func = $GLOBALS['beforeZcFeedRsExt'][$type];
} elseif (is_callable('rsExtPostPublic', $type)) {
$func = ['rsExtPostPublic', $type];
} else {
$func = ['rsExtPost', $type];
}
return call_user_func_array($func, $args);
}
/**
* Get author link from post to feed.
*
* @param dcRecord $rs record instance
* @return string Author link
*/
public static function getAuthorLink(dcRecord $rs): string
{
$author = $rs->zcFeed('author');
$site = $rs->zcFeed('site');
$sitename = $rs->zcFeed('sitename');
return $author && $sitename ?
sprintf('%s (<a href="%s">%s</a>)', $author, $site, $sitename) :
self::zcFeedBrother('getAuthorLink', [&$rs]);
}
/**
* Get author CN from post to feed.
*
* @param dcRecord $rs record instance
* @return string Author CN
*/
public static function getAuthorCN(dcRecord $rs): string
{
$author = $rs->zcFeed('author');
return $author ?
$author :
self::zcFeedBrother('getAuthorCN', [&$rs]);
}
/**
* Get post link from post to feed.
*
* @param dcRecord $rs record instance
* @return string Post link
*/
public static function getURL(dcRecord $rs): string
{
$url = $rs->zcFeed('url');
$types = @unserialize(dcCore::app()->blog->settings->__get(basename(__DIR__))->zoneclearFeedServer_post_title_redir);
$full = is_array($types) && in_array(dcCore::app()->url->type, $types);
return $url && $full ?
zoneclearFeedServer::absoluteURL($rs->zcFeed('site'), $url) :
self::zcFeedBrother('getURL', [&$rs]);
}
/**
* Get post content from post to feed.
*
* @param record $rs record instance
* @return string Post content
*/
public static function getContent(dcRecord $rs, bool $absolute_urls = false): string
{
$url = $rs->zcFeed('url');
$sitename = $rs->zcFeed('sitename');
$content = self::zcFeedBrother('getContent', [&$rs, $absolute_urls]);
if ($url && $sitename && $rs->post_type == 'post') {
$types = @unserialize(dcCore::app()->blog->settings->__get(basename(__DIR__))->zoneclearFeedServer_post_full_tpl);
if (is_array($types) && in_array(dcCore::app()->url->type, $types)) {
return $content . sprintf(
'<p class="zoneclear-original"><em>%s</em></p>',
sprintf(__('Original post on <a href="%s">%s</a>'), $url, $sitename)
);
}
$content = context::remove_html($content);
$content = context::cut_string($content, 350);
$content = html::escapeHTML($content);
return sprintf(
'<p>%s... <em><a href="%s" title="%s">%s</a></em></p>',
$content,
self::getURL($rs),
__('Read more details about this feed'),
__('Continue reading')
);
}
return $content;
}
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - url handler methods.
* @since 2.6
*/
class zcfsUrlHandler extends dcUrlHandlers
{
/**
* Feeds source page and update methods.
*
* @param array $args Page arguments
* @return mixed
*/
public static function zcFeedsPage($args)
{
$s = dcCore::app()->blog->settings->__get(basename(__DIR__));
# Not active
if (!$s->zoneclearFeedServer_active) {
self::p404();
return null;
}
# Update feeds (from ajax or other post resquest)
if ($args == '/zcfsupd' && 3 == $s->zoneclearFeedServer_bhv_pub_upd) {
$msg = '';
if (!empty($_POST['blogId']) && html::escapeJS(dcCore::app()->blog->id) == $_POST['blogId']) {
try {
$zc = new zoneclearFeedServer();
if ($zc->checkFeedsUpdate()) {
$msg = sprintf(
'<status>%s</status><message>s%</message>',
'ok',
'Feeds updated successfully'
);
}
} catch (Exception $e) {
}
}
if (empty($msg)) {
$msg = sprintf(
'<status>%s</status><message>s%</message>',
'failed',
'Failed to update feeds'
);
}
header('Content-Type: application/xml; charset=UTF-8');
echo
'<?xml version="1.0" encoding="utf-8"?> ' . "\n" .
'<response><rsp>' . "\n" .
$msg . "\n" .
'</rsp></response>';
exit(1);
# Server js
} elseif ($args == '/zcfsupd.js' && 3 == $s->zoneclearFeedServer_bhv_pub_upd) {
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates');
self::serveDocument(
'zcfsupd.js',
'text/javascript',
false,
false
);
# Server feeds description page
} elseif (in_array($args, ['', '/']) && $s->zoneclearFeedServer_pub_active) {
$tplset = dcCore::app()->themes->moduleInfo(dcCore::app()->blog->settings->system->theme, 'tplset');
$path = __DIR__ . '/default-templates/';
if (!empty($tplset) && is_dir($path . $tplset)) {
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), $path . $tplset);
} else {
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), $path . DC_DEFAULT_TPLSET);
}
self::serveDocument('zcfeeds.html');
}
# Unknow
else {
self::p404();
}
return null;
}
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - template methods.
* @since 2.6
*/
class zcfsTemplate
{
public static function Feeds($a, $c)
{
$lastn = -1;
$p = '';
if (isset($a['lastn'])) {
$lastn = abs((int) $a['lastn']) + 0;
$p .= "\$zcfs_params['limit'] = " . $lastn . ";\n";
}
if (isset($a['cat_id'])) {
$p .= "@\$zcfs_params['sql'] .= 'AND Z.cat_id = " . addslashes($a['cat_id']) . " ';\n";
}
if (isset($a['no_category'])) {
$p .= "@\$zcfs_params['sql'] .= 'AND Z.cat_id IS NULL ';\n";
}
if (!empty($a['site_url'])) {
$p .= "\$zcfs_params['feed_url'] = '" . addslashes($a['site_url']) . "';\n";
}
if (isset($a['feed_status'])) {
$p .= "\$zcfs_params['feed_status'] = " . ((int) $a['feed_status']) . ";\n";
} else {
$p .= "\$zcfs_params['feed_status'] = 1;\n";
}
if (!empty($a['feed_url'])) {
$p .= "\$zcfs_params['feed_feed'] = '" . addslashes($a['feed_url']) . "';\n";
}
if (isset($a['feed_owner'])) {
$p .= "@\$zcfs_params['sql'] .= \"AND Z.feed_owner = '" . addslashes($a['author']) . "' \";\n";
}
$sortby = 'feed_creadt';
$order = 'desc';
if (isset($a['sortby'])) {
switch ($a['sortby']) {
case 'name': $sortby = 'lowername';
break;
case 'owner': $sortby = 'feed_owner';
break;
case 'date': $sortby = 'feed_dt';
break;
case 'update': $sortby = 'feed_upddt';
break;
case 'id': $sortby = 'feed_id';
break;
}
}
if (isset($a['order']) && preg_match('/^(desc|asc)$/i', $a['order'])) {
$order = $a['order'];
}
$p .= "\$zcfs_params['order'] = '" . $sortby . ' ' . $order . "';\n";
return
'<?php ' . $p .
'dcCore::app()->ctx->feeds_params = $zcfs_params;' . "\n" .
'$zcfs = new zoneclearFeedServer();' . "\n" .
'dcCore::app()->ctx->feeds = $zcfs->getFeeds($zcfs_params); unset($zcfs_params,$zcfs);' . "\n" .
"?>\n" .
'<?php while (dcCore::app()->ctx->feeds->fetch()) : ?>' . $c . '<?php endwhile; ' .
'dcCore::app()->ctx->feeds = null; dcCore::app()->ctx->feeds_params = null; ?>';
}
public static function FeedIf($a, $c)
{
$if = [];
$operator = isset($a['operator']) ? self::getOperator($a['operator']) : '&&';
if (isset($a['type'])) {
$type = trim($a['type']);
$type = !empty($type) ? $type : 'feed';
$if[] = 'dcCore::app()->ctx->feeds->feed_type == "' . addslashes($type) . '"';
}
if (isset($a['site_url'])) {
$url = trim($a['feed_url']);
if (substr($url, 0, 1) == '!') {
$url = substr($url, 1);
$if[] = 'dcCore::app()->ctx->feeds->feed_url != "' . addslashes($url) . '"';
} else {
$if[] = 'dcCore::app()->ctx->feeds->feed_url == "' . addslashes($url) . '"';
}
}
if (isset($a['feed_url'])) {
$url = trim($a['feed_feed']);
if (substr($url, 0, 1) == '!') {
$url = substr($url, 1);
$if[] = 'dcCore::app()->ctx->feeds->feed_feed != "' . addslashes($url) . '"';
} else {
$if[] = 'dcCore::app()->ctx->feeds->feed_feed == "' . addslashes($url) . '"';
}
}
if (isset($a['category'])) {
$category = addslashes(trim($a['category']));
if (substr($category, 0, 1) == '!') {
$category = substr($category, 1);
$if[] = '(dcCore::app()->ctx->feeds->cat_url != "' . $category . '")';
} else {
$if[] = '(dcCore::app()->ctx->feeds->cat_url == "' . $category . '")';
}
}
if (isset($a['first'])) {
$sign = (bool) $a['first'] ? '=' : '!';
$if[] = 'dcCore::app()->ctx->feeds->index() ' . $sign . '= 0';
}
if (isset($a['odd'])) {
$sign = (bool) $a['odd'] ? '=' : '!';
$if[] = '(dcCore::app()->ctx->feeds->index()+1)%2 ' . $sign . ' = 1';
}
if (isset($a['has_category'])) {
$sign = (bool) $a['has_category'] ? '' : '!';
$if[] = $sign . 'dcCore::app()->ctx->feeds->cat_id';
}
if (isset($a['has_description'])) {
$sign = (bool) $a['has_description'] ? '' : '!';
$if[] = $sign . 'dcCore::app()->ctx->feeds->feed_desc';
}
return empty($if) ?
$c :
'<?php if(' . implode(' ' . $operator . ' ', $if) . ') : ?>' . $c . '<?php endif; ?>';
}
public static function FeedIfFirst($a)
{
$ret = $a['return'] ?? 'first';
$ret = html::escapeHTML($ret);
return
'<?php if (dcCore::app()->ctx->feeds->index() == 0) { ' .
"echo '" . addslashes($ret) . "'; } ?>";
}
public static function FeedIfOdd($a)
{
$ret = $a['return'] ?? 'odd';
$ret = html::escapeHTML($ret);
return
'<?php if ((dcCore::app()->ctx->feeds->index()+1)%2 == 1) { ' .
"echo '" . addslashes($ret) . "'; } ?>";
}
public static function FeedDesc($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_desc');
}
public static function FeedOwner($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_owner');
}
public static function FeedCategory($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_title');
}
public static function FeedCategoryID($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_id');
}
public static function FeedCategoryURL($a)
{
return self::getValue($a, 'dcCore::app()->blog->url.dcCore::app()->url->getBase(\'category\').\'/\'.html::sanitizeURL(dcCore::app()->ctx->feeds->cat_url)');
}
public static function FeedCategoryShortURL($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_url');
}
public static function FeedID($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_id');
}
public static function FeedLang($a)
{
$f = dcCore::app()->tpl->getFilters($a);
return empty($a['full']) ?
'<?php echo ' . sprintf($f, 'dcCore::app()->ctx->feeds->feed_lang') . '; ?>' :
'<?php $langs = l10n::getISOcodes(); if (isset($langs[dcCore::app()->ctx->feeds->feed_lang])) { echo ' .
sprintf($f, '$langs[dcCore::app()->ctx->feeds->feed_lang]') . '; } else { echo ' .
sprintf($f, 'dcCore::app()->ctx->feeds->feed_lang') . '; } unset($langs); ?>';
}
public static function FeedName($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_name');
}
public static function FeedSiteURL($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_url');
}
public static function FeedFeedURL($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_feed');
}
public static function FeedsHeader($a, $c)
{
return '<?php if (dcCore::app()->ctx->feeds->isStart()) : ?>' . $c . '<?php endif; ?>';
}
public static function FeedsFooter($a, $c)
{
return '<?php if (dcCore::app()->ctx->feeds->isEnd()) : ?>' . $c . '<?php endif; ?>';
}
public static function FeedsCount($a)
{
$none = 'no sources';
$one = 'one source';
$more = '%d sources';
if (isset($a['none'])) {
$none = addslashes($a['none']);
}
if (isset($a['one'])) {
$one = addslashes($a['one']);
}
if (isset($a['more'])) {
$more = addslashes($a['more']);
}
return
"<?php \$fcount = dcCore::app()->ctx->feeds->count(); \n" .
"if (\$fcount == 0) {\n" .
" printf(__('" . $none . "'),\$fcount);\n" .
"} elseif (\$fcount == 1) {\n" .
" printf(__('" . $one . "'),\$fcount);\n" .
"} else {\n" .
" printf(__('" . $more . "'),\$fcount);\n" .
'} unset($fcount); ?>';
}
public static function FeedsEntriesCount($a)
{
$none = __('no entries');
$one = __('one entry');
$more = __('%d entries');
if (isset($a['none'])) {
$none = addslashes($a['none']);
}
if (isset($a['one'])) {
$one = addslashes($a['one']);
}
if (isset($a['more'])) {
$more = addslashes($a['more']);
}
return
"<?php \$fcount = 0; \n" .
'$zc = new zoneclearFeedServer();' . "\n" .
"\$allfeeds = \$zc->getFeeds(); \n" .
"if (!\$allfeeds->isEmpty()) { \n" .
' while ($allfeeds->fetch()) { ' .
" \$fcount += (integer) \$zc->getPostsByFeed(array('feed_id'=>\$allfeeds->feed_id),true)->f(0); " .
" } \n" .
"} \n" .
"if (\$fcount == 0) {\n" .
" printf(__('" . $none . "'),\$fcount);\n" .
"} elseif (\$fcount == 1) {\n" .
" printf(__('" . $one . "'),\$fcount);\n" .
"} else {\n" .
" printf(__('" . $more . "'),\$fcount);\n" .
'} unset($allfeeds,$fcount); ?>';
}
public static function FeedEntriesCount($a)
{
$none = 'no entries';
$one = 'one entry';
$more = '%d entries';
if (isset($a['none'])) {
$none = addslashes($a['none']);
}
if (isset($a['one'])) {
$one = addslashes($a['one']);
}
if (isset($a['more'])) {
$more = addslashes($a['more']);
}
return
"<?php \$zcfs = new zoneclearFeedServer(); \n" .
"\$fcount = \$zc->getPostsByFeed(array('feed_id'=>dcCore::app()->ctx->feeds->feed_id),true)->f(0); \n" .
"if (\$fcount == 0) {\n" .
" printf(__('" . $none . "'),\$fcount);\n" .
"} elseif (\$fcount == 1) {\n" .
" printf(__('" . $one . "'),\$fcount);\n" .
"} else {\n" .
" printf(__('" . $more . "'),\$fcount);\n" .
'} unset($fcount); ?>';
}
protected static function getValue($a, $v)
{
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), $v) . '; ?>';
}
protected static function getOperator($op)
{
switch (strtolower($op)) {
case 'or':
case '||':
return '||';
case 'and':
case '&&':
default:
return '&&';
}
}
}
dcCore::app()->addBehavior('publicBreadcrumb', ['extZcfeeds', 'publicBreadcrumb']);
class extZcfeeds
{
public static function publicBreadcrumb($context, $separator)
{
if ($context == 'zoneclearFeedsPage') { if ($context == 'zoneclearFeedsPage') {
return __('List of feeds'); return __('List of feeds');
} }
} });
}

View File

@ -14,6 +14,10 @@ if (!defined('DC_RC_PATH')) {
return null; return null;
} }
class zcfsActivityReportBehaviors
{
public static function init()
{
# This file is used with plugin activityReport # This file is used with plugin activityReport
dcCore::app()->activityReport->addGroup( dcCore::app()->activityReport->addGroup(
'zoneclearFeedServer', 'zoneclearFeedServer',
@ -65,9 +69,8 @@ dcCore::app()->activityReport->addAction(
'zoneclearFeedServerAfterEnableFeed', 'zoneclearFeedServerAfterEnableFeed',
['zoneclearFeedServerActivityReportBehaviors', 'enableFeed'] ['zoneclearFeedServerActivityReportBehaviors', 'enableFeed']
); );
}
class zoneclearFeedServerActivityReportBehaviors
{
public static function addFeed($cur) public static function addFeed($cur)
{ {
$logs = [ $logs = [

View File

@ -0,0 +1,243 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - admin methods.
* @since 2.6
*/
class zcfsAdminBehaviors
{
public static function basename()
{
}
public static function feedsSortbyCombo()
{
return [
__('Date') => 'feed_upddt',
__('Name') => 'lowername',
__('Frequency') => 'feed_upd_int',
__('Update date') => 'feed_upd_last',
__('Status') => 'feed_status',
];
}
public static function entriesSortbyCombo()
{
return [
__('Date') => 'post_dt',
__('Title') => 'post_title',
__('Category') => 'cat_title',
__('Author') => 'user_id',
__('Status') => 'post_status',
];
}
/**
* Favorites.
*
* @param dcFavorites $favs Array of favorites
*/
public static function adminDashboardFavoritesV2(dcFavorites $favs)
{
$favs->register('zcfs', [
'title' => __('Feeds server'),
'url' => dcCore::app()->adminurl->get('admin.plugin.' . basename(dirname('../' . __DIR__))),
'small-icon' => dcPage::getPF(basename(dirname('../' . __DIR__)) . '/icon.svg'),
'large-icon' => dcPage::getPF(basename(dirname('../' . __DIR__)) . '/icon.svg'),
'permissions' => dcCore::app()->auth->makePermissions([
dcAuth::PERMISSION_USAGE,
dcAuth::PERMISSION_CONTENT_ADMIN,
]),
'dashboard_cb' => ['zcfsAdminBehaviors', 'adminDashboardFavoritesCallback'],
]);
}
/**
* Favorites hack.
*
* @param arrayObject $fav Fav attributes
*/
public static function adminDashboardFavoritesCallback($fav)
{
$zcfs = new zoneclearFeedServer();
$count = $zcfs->getFeeds(['feed_status' => '0'], true)->f(0);
if (!$count) {
return null;
}
$fav['title'] .= '<br />' . sprintf(__('%s feed disabled', '%s feeds disabled', $count), $count);
$fav['large-icon'] = dcPage::getPF(basename(dirname('../' . __DIR__)) . '/icon-update.svg');
$fav['url'] = dcCore::app()->adminurl->get(
'admin.plugin.' . basename(dirname('../' . __DIR__)),
['part' => 'feeds', 'sortby' => 'feed_status', 'order' => 'asc']
);
}
/**
* User pref columns lists.
*
* @param arrayObject $cols Columns
*/
public static function adminColumnsListsV2($cols)
{
$cols['zcfs_feeds'] = [
__('Feeds server: Feeds'),
[
'desc' => [true, __('Feed')],
'period' => [true, __('Frequency')],
'update' => [true, __('Last update')],
'entries' => [true, __('Entries')],
],
];
$cols['zcfs_entries'] = [
__('Feeds server: Entries'),
[
'date' => [true, __('Date')],
'category' => [true, __('Category')],
'author' => [true, __('Author')],
],
];
}
/**
* User pref filters options.
*
* @param arrayObject $sorts Sort options
*/
public static function adminFiltersListsV2($sorts)
{
$sorts['zcfs_feeds'] = [
__('Feeds server: Feeds'),
self::feedsSortbyCombo(),
'lowername',
'asc',
[__('feeds per page'), 30],
];
$sorts['zcfs_entries'] = [
__('Feeds server: Entries'),
self::entriesSortbyCombo(),
'post_dt',
'desc',
[__('entries per page'), 30],
];
}
/**
* Add javascript for toggle to post edition page header.
*
* @return string Page header
*/
public static function adminPostHeaders()
{
return dcPage::jsLoad(dcPage::getPF(basename(dirname('../' . __DIR__)) . '/js/post.js'));
}
/**
* Add form to post sidebar.
*
* @param ArrayObject $main_items Main items
* @param ArrayObject $sidebar_items Sidebar items
* @param record $post Post record or null
*/
public static function adminPostFormItems(ArrayObject $main_items, ArrayObject $sidebar_items, $post)
{
if ($post === null || $post->post_type != 'post') {
return null;
}
$url = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_url',
'limit' => 1,
]);
$url = $url->isEmpty() ? '' : $url->meta_id;
if (!$url) {
return null;
}
$author = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_author',
'limit' => 1,
]);
$author = $author->isEmpty() ? '' : $author->meta_id;
$site = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_site',
'limit' => 1,
]);
$site = $site->isEmpty() ? '' : $site->meta_id;
$sitename = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_sitename',
'limit' => 1,
]);
$sitename = $sitename->isEmpty() ? '' : $sitename->meta_id;
$edit = '';
if (dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_CONTENT_ADMIN]), dcCore::app()->blog->id)) {
$fid = dcCore::app()->meta->getMetadata([
'post_id' => $post->post_id,
'meta_type' => 'zoneclearfeed_id',
'limit' => 1,
]);
if (!$fid->isEmpty()) {
$edit = sprintf(
'<p><a href="%s">%s</a></p>',
dcCore::app()->adminurl->get(
'admin.plugin.' . basename(dirname('../' . __DIR__)),
['part' => 'feed', 'feed_id' => $fid->meta_id]
),
__('Edit this feed')
);
}
}
$sidebar_items['options-box']['items']['zcfs'] = '<div id="zcfs">' .
'<h5>' . __('Feed source') . '</h5>' .
'<p>' .
'<a href="' . $url . '" title="' . $author . ' - ' . $url . '">' . __('feed URL') . '</a> - ' .
'<a href="' . $site . '" title="' . $sitename . ' - ' . $site . '">' . __('site URL') . '</a>' .
'</p>' .
$edit .
'</div>';
}
/**
* Delete related info about feed post in meta table.
*
* @param integer $post_id Post id
*/
public static function adminBeforePostDelete($post_id)
{
dcCore::app()->con->execute(
'DELETE FROM ' . dcCore::app()->prefix . dcMeta::META_TABLE_NAME . ' ' .
'WHERE post_id = ' . ((int) $post_id) . ' ' .
'AND meta_type ' . dcCore::app()->con->in([
'zoneclearfeed_url',
'zoneclearfeed_author',
'zoneclearfeed_site',
'zoneclearfeed_sitename',
'zoneclearfeed_id',
]) . ' '
);
}
}

View File

@ -0,0 +1,308 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Feeds server - Default actions methods
* @since 2.6
* @see dcDefaultPostsActionsPage for mor info
*/
class zcfsDefaultFeedsActions
{
public static function zcfsFeedsActions(zcfsFeedsActions $ap)
{
$ap->addAction(
[__('Change category') => 'changecat'],
['zcfsDefaultFeedsActions', 'doChangeCategory']
);
$ap->addAction(
[__('Change update interval') => 'changeint'],
['zcfsDefaultFeedsActions', 'doChangeInterval']
);
$ap->addAction(
[__('Disable feed update') => 'disablefeed'],
['zcfsDefaultFeedsActions', 'doEnableFeed']
);
$ap->addAction(
[__('Enable feed update') => 'enablefeed'],
['zcfsDefaultFeedsActions', 'doEnableFeed']
);
$ap->addAction(
[__('Reset last update') => 'resetupdlast'],
['zcfsDefaultFeedsActions', 'doResetUpdate']
);
$ap->addAction(
[__('Update (check) feed') => 'updatefeed'],
['zcfsDefaultFeedsActions', 'doUpdateFeed']
);
$ap->addAction(
[__('Delete related posts') => 'deletepost'],
['zcfsDefaultFeedsActions', 'doDeletePost']
);
$ap->addAction(
[__('Delete feed (without related posts)') => 'deletefeed'],
['zcfsDefaultFeedsActions', 'doDeleteFeed']
);
}
public static function doEnableFeed(zcfsFeedsActions $ap, $post)
{
$enable = $ap->getAction() == 'enablefeed';
$ids = $ap->getIDs();
if (empty($ids)) {
throw new Exception(__('No feeds selected'));
}
foreach ($ids as $id) {
$ap->zcfs->enableFeed($id, $enable);
}
dcAdminNotices::addSuccessNotice(sprintf(
$enable ?
__(
'%d feed has been successfully enabled.',
'%d feeds have been successfully enabled.',
count($ids)
)
:
__(
'%d feed has been successfully disabled.',
'%d feeds have been successfully disabled.',
count($ids)
),
count($ids)
));
$ap->redirect(true);
}
public static function doDeletePost(zcfsFeedsActions $ap, $post)
{
$types = [
'zoneclearfeed_url',
'zoneclearfeed_author',
'zoneclearfeed_site',
'zoneclearfeed_sitename',
'zoneclearfeed_id',
];
$ids = $ap->getIDs();
if (empty($ids)) {
throw new Exception(__('No feeds selected'));
}
foreach ($ids as $id) {
$posts = $ap->zcfs->getPostsByFeed([
'feed_id' => $id,
]);
while ($posts->fetch()) {
dcCore::app()->blog->delPost($posts->post_id);
dcCore::app()->con->execute(
'DELETE FROM ' . dcCore::app()->prefix . dcMeta::META_TABLE_NAME . ' ' .
'WHERE post_id = ' . $posts->post_id . ' ' .
'AND meta_type ' . dcCore::app()->con->in($types) . ' '
);
}
}
dcAdminNotices::addSuccessNotice(
__('Entries have been successfully deleted.')
);
$ap->redirect(true);
}
public static function doDeleteFeed(zcfsFeedsActions $ap, $post)
{
$ids = $ap->getIDs();
if (empty($ids)) {
throw new Exception(__('No feeds selected'));
}
foreach ($ids as $id) {
$ap->zcfs->delFeed($id);
}
dcAdminNotices::addSuccessNotice(sprintf(
__(
'%d feed has been successfully deleted.',
'%d feeds have been successfully deleted.',
count($ids)
),
count($ids)
));
$ap->redirect(true);
}
public static function doUpdateFeed(zcfsFeedsActions $ap, $post)
{
$ids = $ap->getIDs();
if (empty($ids)) {
throw new Exception(__('No feeds selected'));
}
foreach ($ids as $id) {
$ap->zcfs->checkFeedsUpdate($id, true);
}
dcAdminNotices::addSuccessNotice(sprintf(
__(
'%d feed has been successfully updated.',
'%d feeds have been successfully updated.',
count($ids)
),
count($ids)
));
$ap->redirect(true);
}
public static function doResetUpdate(zcfsFeedsActions $ap, $post)
{
$ids = $ap->getIDs();
if (empty($ids)) {
throw new Exception(__('No feeds selected'));
}
foreach ($ids as $id) {
$cur = $ap->zcfs->openCursor();
$cur->feed_upd_last = 0;
$ap->zcfs->updFeed($id, $cur);
$ap->zcfs->checkFeedsUpdate($id, true);
}
dcAdminNotices::addSuccessNotice(sprintf(
__(
'Last update of %s feed successfully reseted.',
'Last update of %s feeds successfully reseted.',
count($ids)
),
count($ids)
));
$ap->redirect(true);
}
public static function doChangeCategory(zcfsFeedsActions $ap, $post)
{
if (isset($post['upd_cat_id'])) {
$ids = $ap->getIDs();
if (empty($ids)) {
throw new Exception(__('No feeds selected'));
}
$cat_id = abs((int) $post['upd_cat_id']);
foreach ($ids as $id) {
$cur = $ap->zcfs->openCursor();
$cur->cat_id = $cat_id == 0 ? null : $cat_id;
$ap->zcfs->updFeed($id, $cur);
}
dcAdminNotices::addSuccessNotice(sprintf(
__(
'Category of %s feed successfully changed.',
'Category of %s feeds successfully changed.',
count($ids)
),
count($ids)
));
$ap->redirect(true);
} else {
$categories_combo = dcAdminCombos::getCategoriesCombo(
dcCore::app()->blog->getCategories()
);
$ap->beginPage(
dcPage::breadcrumb([
html::escapeHTML(dcCore::app()->blog->name) => '',
__('Feeds server') => '',
$ap->getCallerTitle() => $ap->getRedirection(true),
__('Change category for this selection') => '',
])
);
echo
'<form action="' . $ap->getURI() . '" method="post">' .
$ap->getCheckboxes() .
'<p><label for="upd_cat_id" class="classic">' . __('Category:') . '</label> ' .
form::combo(['upd_cat_id'], $categories_combo, '') .
dcCore::app()->formNonce() .
$ap->getHiddenFields() .
form::hidden(['action'], 'changecat') .
'<input type="submit" value="' . __('Save') . '" /></p>' .
'</form>';
$ap->endPage();
}
}
public static function doChangeInterval(zcfsFeedsActions $ap, $post)
{
if (isset($post['upd_upd_int'])) {
$ids = $ap->getIDs();
if (empty($ids)) {
throw new Exception(__('No feeds selected'));
}
$upd_int = abs((int) $post['upd_upd_int']);
foreach ($ids as $id) {
$cur = $ap->zcfs->openCursor();
$cur->feed_upd_int = $upd_int;
$ap->zcfs->updFeed($id, $cur);
}
dcAdminNotices::addSuccessNotice(sprintf(
__(
'Update frequency of %s feed successfully changed.',
'Update frequency of %s feeds successfully changed.',
count($ids)
),
count($ids)
));
$ap->redirect(true);
} else {
$ap->beginPage(
dcPage::breadcrumb(
[
html::escapeHTML(dcCore::app()->blog->name) => '',
__('Feeds server') => '',
$ap->getCallerTitle() => $ap->getRedirection(true),
__('Change update frequency for this selection') => '',
]
)
);
echo
'<form action="' . $ap->getURI() . '" method="post">' .
$ap->getCheckboxes() .
'<p><label for="upd_upd_int" class="classic">' . __('Frequency:') . '</label> ' .
form::combo(['upd_upd_int'], $ap->zcfs->getAllUpdateInterval(), '') .
dcCore::app()->formNonce() .
$ap->getHiddenFields() .
form::hidden(['action'], 'changeint') .
'<input type="submit" value="' . __('Save') . '" /></p>' .
'</form>';
$ap->endPage();
}
}
}

View File

@ -0,0 +1,148 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Feeds server - Posts list methods
* @since 2.6
* @see adminGenericList for more info
*/
class zcfsEntriesList extends adminGenericList
{
public function display($page, $nb_per_page, $base_url, $enclose_block = '', $filter = false)
{
if ($this->rs->isEmpty()) {
echo '<p><strong>' . (
$filter ?
__('No entries matches the filter') :
__('No entries')
) . '</strong></p>';
} else {
$pager = new dcPager($page, $this->rs_count, $nb_per_page, 10);
$pager->base_url = $base_url;
$entries = [];
if (isset($_REQUEST['feeds'])) {
foreach ($_REQUEST['feeds'] as $v) {
$entries[(int) $v] = true;
}
}
$html_block = '<div class="table-outer clear">' .
'<table>' .
'<caption>' . (
$filter ?
sprintf(__('List of %s entries matching the filter.'), $this->rs_count) :
sprintf(__('List of entries (%s)'), $this->rs_count)
) . '</caption>';
$cols = [
'title' => '<th scope="col" colspan="2" class="first">' . __('Title') . '</th>',
'date' => '<th scope="col">' . __('Date') . '</th>',
'author' => '<th scope="col">' . __('Author') . '</th>',
'category' => '<th scope="col">' . __('Category') . '</th>',
'status' => '<th scope="col">' . __('Status') . '</th>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsPostListHeader', $this->rs, $cols);
$this->userColumns('zcfs_entries', $cols);
$html_block .= '<tr>' . implode(iterator_to_array($cols)) . '</tr>%s</table></div>';
if ($enclose_block) {
$html_block = sprintf($enclose_block, $html_block);
}
echo $pager->getLinks();
$blocks = explode('%s', $html_block);
echo $blocks[0];
while ($this->rs->fetch()) {
echo $this->postLine();
}
echo $blocks[1];
echo $pager->getLinks();
}
}
private function postLine()
{
$cat_link = dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_CATEGORIES]), dcCore::app()->blog->id) ?
'<a href="category.php?id=%s" title="' . __('Edit category') . '">%s</a>'
: '%2$s';
$cat_title = $this->rs->cat_title ?
sprintf($cat_link, $this->rs->cat_id, html::escapeHTML($this->rs->cat_title))
: __('None');
$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
$img_status = '';
$sts_class = '';
switch ($this->rs->post_status) {
case 1:
$img_status = sprintf($img, __('Published'), 'check-on.png');
$sts_class = 'sts-online';
break;
case 0:
$img_status = sprintf($img, __('Unpublished'), 'check-off.png');
$sts_class = 'sts-offline';
break;
case -1:
$img_status = sprintf($img, __('Scheduled'), 'scheduled.png');
$sts_class = 'sts-scheduled';
break;
case -2:
$img_status = sprintf($img, __('Pending'), 'check-wrn.png');
$sts_class = 'sts-pending';
break;
}
$res = '<tr class="line ' . ($this->rs->post_status != 1 ? 'offline ' : '') . $sts_class . '"' .
' id="p' . $this->rs->post_id . '">';
$cols = [
'check' => '<td class="nowrap minimal">' .
form::checkbox(['entries[]'], $this->rs->post_id, '', '', '', !$this->rs->isEditable()) . '</td>',
'title' => '<td scope="row" class="maximal"><a href="' .
dcCore::app()->getPostAdminURL($this->rs->post_type, $this->rs->post_id) . '" ' .
'title="' . html::escapeHTML($this->rs->getURL()) . '">' .
html::escapeHTML(trim(html::clean($this->rs->post_title))) . '</a></td>',
'date' => '<td class="nowrap count">' . dt::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->post_dt) . '</td>',
'author' => '<td class="nowrap">' . html::escapeHTML($this->rs->user_id) . '</td>',
'category' => '<td class="nowrap">' . $cat_title . '</td>',
'status' => '<td class="nowrap status">' . $img_status . '</td>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsPostListValue', $this->rs, $cols);
$this->userColumns('zcfs_entries', $cols);
$res .= implode(iterator_to_array($cols));
$res .= '</tr>';
return $res;
}
}

View File

@ -10,7 +10,11 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class zcfsFeedsActionsPage extends dcActions if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
class zcfsFeedsActions extends dcActions
{ {
public $zcfs; public $zcfs;
@ -29,8 +33,8 @@ class zcfsFeedsActionsPage extends dcActions
protected function loadDefaults() protected function loadDefaults()
{ {
zcfsDefaultFeedsActions::zcfsFeedsActionsPage($this); zcfsDefaultFeedsActions::zcfsFeedsActions($this);
dcCore::app()->callBehavior('zcfsFeedsActionsPage', $this); dcCore::app()->callBehavior('zcfsFeedsActions', $this);
} }
public function beginPage($breadcrumb = '', $head = '') public function beginPage($breadcrumb = '', $head = '')
@ -89,7 +93,7 @@ class zcfsFeedsActionsPage extends dcActions
*/ */
class zcfsDefaultFeedsActions class zcfsDefaultFeedsActions
{ {
public static function zcfsFeedsActionsPage(zcfsFeedsActionsPage $ap) public static function zcfsFeedsActions(zcfsFeedsActions $ap)
{ {
$ap->addAction( $ap->addAction(
[__('Change category') => 'changecat'], [__('Change category') => 'changecat'],
@ -125,7 +129,7 @@ class zcfsDefaultFeedsActions
); );
} }
public static function doEnableFeed(zcfsFeedsActionsPage $ap, $post) public static function doEnableFeed(zcfsFeedsActions $ap, $post)
{ {
$enable = $ap->getAction() == 'enablefeed'; $enable = $ap->getAction() == 'enablefeed';
$ids = $ap->getIDs(); $ids = $ap->getIDs();
@ -156,7 +160,7 @@ class zcfsDefaultFeedsActions
$ap->redirect(true); $ap->redirect(true);
} }
public static function doDeletePost(zcfsFeedsActionsPage $ap, $post) public static function doDeletePost(zcfsFeedsActions $ap, $post)
{ {
$types = [ $types = [
'zoneclearfeed_url', 'zoneclearfeed_url',
@ -193,7 +197,7 @@ class zcfsDefaultFeedsActions
$ap->redirect(true); $ap->redirect(true);
} }
public static function doDeleteFeed(zcfsFeedsActionsPage $ap, $post) public static function doDeleteFeed(zcfsFeedsActions $ap, $post)
{ {
$ids = $ap->getIDs(); $ids = $ap->getIDs();
@ -216,7 +220,7 @@ class zcfsDefaultFeedsActions
$ap->redirect(true); $ap->redirect(true);
} }
public static function doUpdateFeed(zcfsFeedsActionsPage $ap, $post) public static function doUpdateFeed(zcfsFeedsActions $ap, $post)
{ {
$ids = $ap->getIDs(); $ids = $ap->getIDs();
@ -239,7 +243,7 @@ class zcfsDefaultFeedsActions
$ap->redirect(true); $ap->redirect(true);
} }
public static function doResetUpdate(zcfsFeedsActionsPage $ap, $post) public static function doResetUpdate(zcfsFeedsActions $ap, $post)
{ {
$ids = $ap->getIDs(); $ids = $ap->getIDs();
@ -265,7 +269,7 @@ class zcfsDefaultFeedsActions
$ap->redirect(true); $ap->redirect(true);
} }
public static function doChangeCategory(zcfsFeedsActionsPage $ap, $post) public static function doChangeCategory(zcfsFeedsActions $ap, $post)
{ {
if (isset($post['upd_cat_id'])) { if (isset($post['upd_cat_id'])) {
$ids = $ap->getIDs(); $ids = $ap->getIDs();
@ -320,7 +324,7 @@ class zcfsDefaultFeedsActions
} }
} }
public static function doChangeInterval(zcfsFeedsActionsPage $ap, $post) public static function doChangeInterval(zcfsFeedsActions $ap, $post)
{ {
if (isset($post['upd_upd_int'])) { if (isset($post['upd_upd_int'])) {
$ids = $ap->getIDs(); $ids = $ap->getIDs();

View File

@ -0,0 +1,141 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Feeds server - feeds list methods
* @since 2.6
* @see adminGenericList for more info
*/
class zcfsFeedsList extends adminGenericList
{
private $zc = null;
public function feedsDisplay($page, $nb_per_page, $enclose_block = '', $filter = false)
{
if ($this->rs->isEmpty()) {
if ($filter) {
echo '<p><strong>' . __('No feeds matches the filter') . '</strong></p>';
} else {
echo '<p><strong>' . __('No feeds') . '</strong></p>';
}
} else {
$this->zc = new zoneclearFeedServer();
$pager = new dcPager($page, $this->rs_count, $nb_per_page, 10);
$entries = [];
if (isset($_REQUEST['feeds'])) {
foreach ($_REQUEST['feeds'] as $v) {
$entries[(int) $v] = true;
}
}
$html_block = '<div class="table-outer">' .
'<table>' .
'<caption>' . (
$filter ?
sprintf(__('List of %s feeds matching the filter.'), $this->rs_count) :
sprintf(__('List of feeds (%s)'), $this->rs_count)
) . '</caption>';
$cols = [
'title' => '<th colspan="2" class="first">' . __('Name') . '</th>',
'desc' => '<th scope="col">' . __('Feed') . '</th>',
'period' => '<th scope="col">' . __('Frequency') . '</th>',
'update' => '<th scope="col">' . __('Last update') . '</th>',
'entries' => '<th scope="col">' . __('Entries') . '</th>',
'status' => '<th scope="col">' . __('Status') . '</th>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsFeedsListHeader', $this->rs, $cols);
$this->userColumns('zcfs_feeds', $cols);
$html_block .= '<tr>' . implode(iterator_to_array($cols)) . '</tr>%s</table>%s</div>';
if ($enclose_block) {
$html_block = sprintf($enclose_block, $html_block);
}
echo $pager->getLinks();
$blocks = explode('%s', $html_block);
echo $blocks[0];
while ($this->rs->fetch()) {
echo $this->feedsLine(isset($entries[$this->rs->feed_id]));
}
echo $blocks[1];
echo $blocks[2];
echo $pager->getLinks();
}
}
private function feedsLine($checked)
{
$combo_status = zoneclearFeedServer::getAllStatus();
$combo_upd_int = zoneclearFeedServer::getAllUpdateInterval();
$status = $this->rs->feed_status ?
'<img src="images/check-on.png" alt="enable" />' :
'<img src="images/check-off.png" alt="disable" />';
$entries_count = $this->zc->getPostsByFeed(['feed_id' => $this->rs->feed_id], true)->f(0);
$shunk_feed = $this->rs->feed_feed;
if (strlen($shunk_feed) > 83) {
$shunk_feed = substr($shunk_feed, 0, 50) . '...' . substr($shunk_feed, -20);
}
$url = dcCore::app()->adminurl->get('admin.plugin.' . basename(dirname('../' . __DIR__)), ['part' => 'feed', 'feed_id' => $this->rs->feed_id]);
$cols = [
'check' => '<td class="nowrap minimal">' .
form::checkbox(['feeds[]'], $this->rs->feed_id, ['checked' => $checked]) .
'</td>',
'title' => '<td class="nowrap" scope="row">' .
'<a href="' . $url . '#feed" title="' . __('Edit') . '">' . html::escapeHTML($this->rs->feed_name) . '</a>' .
'</td>',
'desc' => '<td class="nowrap maximal">' .
'<a href="' . $this->rs->feed_feed . '" title="' . html::escapeHTML($this->rs->feed_desc) . '">' . html::escapeHTML($shunk_feed) . '</a>' .
'</td>',
'period' => '<td class="nowrap minimal count">' .
array_search($this->rs->feed_upd_int, $combo_upd_int) .
'</td>',
'update' => '<td class="nowrap minimal count">' .
(
$this->rs->feed_upd_last < 1 ?
__('never') :
dt::str(__('%Y-%m-%d %H:%M'), (int) $this->rs->feed_upd_last, dcCore::app()->auth->getInfo('user_tz'))
) . '</td>',
'entries' => '<td class="nowrap minimal count">' .
(
$entries_count ?
'<a href="' . $url . '#entries" title="' . __('View entries') . '">' . $entries_count . '</a>' :
$entries_count
) . '</td>',
'status' => '<td class="nowrap minimal status">' . $status . '</td>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsFeedsListValue', $this->rs, $cols);
$this->userColumns('zcfs_feeds', $cols);
return
'<tr class="line ' . ($this->rs->feed_status ? '' : 'offline ') . '" id="p' . $this->rs->feed_id . '">' .
implode(iterator_to_array($cols)) .
'</tr>';
}
}

View File

@ -0,0 +1,153 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Feeds server - Posts list filters methods
* @since 2.20
* @see adminGenericFilter for more info
*/
class zcfsPostFilter extends adminGenericFilter
{
public function __construct()
{
parent::__construct(dcCore::app(), 'zcfs_entries');
$filters = new arrayObject([
dcAdminFilters::getPageFilter(),
$this->getPostUserFilter(),
$this->getPostCategoriesFilter(),
$this->getPostStatusFilter(),
$this->getPostMonthFilter(),
]);
# --BEHAVIOR-- zcfsPostFilter
dcCore::app()->callBehavior('zcfsPostFilter', $filters);
$filters = $filters->getArrayCopy();
$this->add($filters);
}
/**
* Posts users select
*/
public function getPostUserFilter(): ?dcAdminFilter
{
$users = null;
try {
$users = dcCore::app()->blog->getPostsUsers();
if ($users->isEmpty()) {
return null;
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return null;
}
$combo = dcAdminCombos::getUsersCombo($users);
dcUtils::lexicalKeySort($combo);
return (new dcAdminFilter('user_id'))
->param()
->title(__('Author:'))
->options(array_merge(
['-' => ''],
$combo
))
->prime(true);
}
/**
* Posts categories select
*/
public function getPostCategoriesFilter(): ?dcAdminFilter
{
$categories = null;
try {
$categories = dcCore::app()->blog->getCategories();
if ($categories->isEmpty()) {
return null;
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return null;
}
$combo = [
'-' => '',
__('(No cat)') => 'NULL',
];
while ($categories->fetch()) {
$combo[
str_repeat('&nbsp;', ($categories->level - 1) * 4) .
html::escapeHTML($categories->cat_title) . ' (' . $categories->nb_post . ')'
] = $categories->cat_id;
}
return (new dcAdminFilter('cat_id'))
->param()
->title(__('Category:'))
->options($combo)
->prime(true);
}
/**
* Posts status select
*/
public function getPostStatusFilter(): dcAdminFilter
{
return (new dcAdminFilter('status'))
->param('post_status')
->title(__('Status:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getPostStatusesCombo()
));
}
/**
* Posts by month select
*/
public function getPostMonthFilter(): ?dcAdminFilter
{
$dates = null;
try {
$dates = dcCore::app()->blog->getDates(['type' => 'month']);
if ($dates->isEmpty()) {
return null;
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return null;
}
return (new dcAdminFilter('month'))
->param('post_month', function ($f) { return substr($f[0], 4, 2); })
->param('post_year', function ($f) { return substr($f[0], 0, 4); })
->title(__('Month:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getDatesCombo($dates)
));
}
}

View File

@ -0,0 +1,87 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_RC_PATH')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - public methods.
* @since 2.6
*/
class zcfsPublicBehaviors
{
/**
* Remember others post extension.
*
* @param dcRecord $rs record instance
*/
public static function coreBlogGetPosts(dcRecord $rs)
{
$GLOBALS['beforeZcFeedRsExt'] = $rs->extensions();
$rs->extend('zcfsRsExtPosts');
}
/**
* Update feeds after contents.
*/
public static function publicAfterDocumentV2()
{
# Limit feeds update to home page et feed page
# Like publishScheduledEntries
if (!in_array(dcCore::app()->url->type, ['default', 'feed'])) {
return null;
}
self::publicDocument();
}
/**
* Generic behavior for before and after public content.
*/
public static function publicDocumentV2()
{
$zc = new zoneclearFeedServer();
$zc->checkFeedsUpdate();
return null;
}
/**
* Update feeds by an Ajax request (background).
*/
public static function publicHeadContent()
{
# Limit update to home page
if (dcCore::app()->url->type != 'default') {
return null;
}
$blog_url = html::escapeJS(
dcCore::app()->blog->url .
dcCore::app()->url->getBase('zoneclearFeedsPage') .
'/zcfsupd'
);
$blog_id = html::escapeJS(dcCore::app()->blog->id);
echo
"\n<!-- JS for zoneclearFeedServer --> \n" .
dcUtils::jsLoad(dcCore::app()->blog->url . dcCore::app()->url->getBase('zoneclearFeedsPage') . '/zcfsupd.js') .
"<script type=\"text/javascript\"> \n//<![CDATA[\n" .
' $(function(){if(!document.getElementById){return;} ' .
" $('body').zoneclearFeedServer({blog_url:'" .
$blog_url . "',blog_id:'" . $blog_id . "'}); " .
" })\n" .
"//]]>\n</script>\n";
}
}

View File

@ -0,0 +1,152 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_RC_PATH')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - rs methods.
* @since 2.6
*/
class zcfsRsExtPosts extends rsExtPost
{
public static function zc()
{
return new zoneclearFeedServer();
}
/**
* Get feed meta.
*
* @param dcRecord $rs record instance
* @param string $info Feed info key
* @return string Feed info value
*/
public static function zcFeed($rs, $info)
{
$meta = dcCore::app()->meta->getMetadata([
'post_id' => $rs->post_id,
'meta_type' => 'zoneclearfeed_' . $info,
'limit' => 1,
]);
return $meta->isEmpty() ? null : $meta->meta_id;
}
/**
* Call other rs extension.
*
* @param string $type Type of extension
* @param array $args Arguments
* @return mixed record extension ressource
*/
public static function zcFeedBrother($type, $args)
{
if (!empty($GLOBALS['beforeZcFeedRsExt'][$type])) {
$func = $GLOBALS['beforeZcFeedRsExt'][$type];
} elseif (is_callable('rsExtPostPublic', $type)) {
$func = ['rsExtPostPublic', $type];
} else {
$func = ['rsExtPost', $type];
}
return call_user_func_array($func, $args);
}
/**
* Get author link from post to feed.
*
* @param dcRecord $rs record instance
* @return string Author link
*/
public static function getAuthorLink(dcRecord $rs): string
{
$author = $rs->zcFeed('author');
$site = $rs->zcFeed('site');
$sitename = $rs->zcFeed('sitename');
return $author && $sitename ?
sprintf('%s (<a href="%s">%s</a>)', $author, $site, $sitename) :
self::zcFeedBrother('getAuthorLink', [&$rs]);
}
/**
* Get author CN from post to feed.
*
* @param dcRecord $rs record instance
* @return string Author CN
*/
public static function getAuthorCN(dcRecord $rs): string
{
$author = $rs->zcFeed('author');
return $author ?
$author :
self::zcFeedBrother('getAuthorCN', [&$rs]);
}
/**
* Get post link from post to feed.
*
* @param dcRecord $rs record instance
* @return string Post link
*/
public static function getURL(dcRecord $rs): string
{
$url = $rs->zcFeed('url');
$types = @unserialize(dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)))->zoneclearFeedServer_post_title_redir);
$full = is_array($types) && in_array(dcCore::app()->url->type, $types);
return $url && $full ?
zoneclearFeedServer::absoluteURL($rs->zcFeed('site'), $url) :
self::zcFeedBrother('getURL', [&$rs]);
}
/**
* Get post content from post to feed.
*
* @param record $rs record instance
* @return string Post content
*/
public static function getContent(dcRecord $rs, bool $absolute_urls = false): string
{
$url = $rs->zcFeed('url');
$sitename = $rs->zcFeed('sitename');
$content = self::zcFeedBrother('getContent', [&$rs, $absolute_urls]);
if ($url && $sitename && $rs->post_type == 'post') {
$types = @unserialize(dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)))->zoneclearFeedServer_post_full_tpl);
if (is_array($types) && in_array(dcCore::app()->url->type, $types)) {
return $content . sprintf(
'<p class="zoneclear-original"><em>%s</em></p>',
sprintf(__('Original post on <a href="%s">%s</a>'), $url, $sitename)
);
}
$content = context::remove_html($content);
$content = context::cut_string($content, 350);
$content = html::escapeHTML($content);
return sprintf(
'<p>%s... <em><a href="%s" title="%s">%s</a></em></p>',
$content,
self::getURL($rs),
__('Read more details about this feed'),
__('Continue reading')
);
}
return $content;
}
}

View File

@ -0,0 +1,346 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_RC_PATH')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - template methods.
* @since 2.6
*/
class zcfsTemplate
{
public static function Feeds($a, $c)
{
$lastn = -1;
$p = '';
if (isset($a['lastn'])) {
$lastn = abs((int) $a['lastn']) + 0;
$p .= "\$zcfs_params['limit'] = " . $lastn . ";\n";
}
if (isset($a['cat_id'])) {
$p .= "@\$zcfs_params['sql'] .= 'AND Z.cat_id = " . addslashes($a['cat_id']) . " ';\n";
}
if (isset($a['no_category'])) {
$p .= "@\$zcfs_params['sql'] .= 'AND Z.cat_id IS NULL ';\n";
}
if (!empty($a['site_url'])) {
$p .= "\$zcfs_params['feed_url'] = '" . addslashes($a['site_url']) . "';\n";
}
if (isset($a['feed_status'])) {
$p .= "\$zcfs_params['feed_status'] = " . ((int) $a['feed_status']) . ";\n";
} else {
$p .= "\$zcfs_params['feed_status'] = 1;\n";
}
if (!empty($a['feed_url'])) {
$p .= "\$zcfs_params['feed_feed'] = '" . addslashes($a['feed_url']) . "';\n";
}
if (isset($a['feed_owner'])) {
$p .= "@\$zcfs_params['sql'] .= \"AND Z.feed_owner = '" . addslashes($a['author']) . "' \";\n";
}
$sortby = 'feed_creadt';
$order = 'desc';
if (isset($a['sortby'])) {
switch ($a['sortby']) {
case 'name': $sortby = 'lowername';
break;
case 'owner': $sortby = 'feed_owner';
break;
case 'date': $sortby = 'feed_dt';
break;
case 'update': $sortby = 'feed_upddt';
break;
case 'id': $sortby = 'feed_id';
break;
}
}
if (isset($a['order']) && preg_match('/^(desc|asc)$/i', $a['order'])) {
$order = $a['order'];
}
$p .= "\$zcfs_params['order'] = '" . $sortby . ' ' . $order . "';\n";
return
'<?php ' . $p .
'dcCore::app()->ctx->feeds_params = $zcfs_params;' . "\n" .
'$zcfs = new zoneclearFeedServer();' . "\n" .
'dcCore::app()->ctx->feeds = $zcfs->getFeeds($zcfs_params); unset($zcfs_params,$zcfs);' . "\n" .
"?>\n" .
'<?php while (dcCore::app()->ctx->feeds->fetch()) : ?>' . $c . '<?php endwhile; ' .
'dcCore::app()->ctx->feeds = null; dcCore::app()->ctx->feeds_params = null; ?>';
}
public static function FeedIf($a, $c)
{
$if = [];
$operator = isset($a['operator']) ? self::getOperator($a['operator']) : '&&';
if (isset($a['type'])) {
$type = trim($a['type']);
$type = !empty($type) ? $type : 'feed';
$if[] = 'dcCore::app()->ctx->feeds->feed_type == "' . addslashes($type) . '"';
}
if (isset($a['site_url'])) {
$url = trim($a['feed_url']);
if (substr($url, 0, 1) == '!') {
$url = substr($url, 1);
$if[] = 'dcCore::app()->ctx->feeds->feed_url != "' . addslashes($url) . '"';
} else {
$if[] = 'dcCore::app()->ctx->feeds->feed_url == "' . addslashes($url) . '"';
}
}
if (isset($a['feed_url'])) {
$url = trim($a['feed_feed']);
if (substr($url, 0, 1) == '!') {
$url = substr($url, 1);
$if[] = 'dcCore::app()->ctx->feeds->feed_feed != "' . addslashes($url) . '"';
} else {
$if[] = 'dcCore::app()->ctx->feeds->feed_feed == "' . addslashes($url) . '"';
}
}
if (isset($a['category'])) {
$category = addslashes(trim($a['category']));
if (substr($category, 0, 1) == '!') {
$category = substr($category, 1);
$if[] = '(dcCore::app()->ctx->feeds->cat_url != "' . $category . '")';
} else {
$if[] = '(dcCore::app()->ctx->feeds->cat_url == "' . $category . '")';
}
}
if (isset($a['first'])) {
$sign = (bool) $a['first'] ? '=' : '!';
$if[] = 'dcCore::app()->ctx->feeds->index() ' . $sign . '= 0';
}
if (isset($a['odd'])) {
$sign = (bool) $a['odd'] ? '=' : '!';
$if[] = '(dcCore::app()->ctx->feeds->index()+1)%2 ' . $sign . ' = 1';
}
if (isset($a['has_category'])) {
$sign = (bool) $a['has_category'] ? '' : '!';
$if[] = $sign . 'dcCore::app()->ctx->feeds->cat_id';
}
if (isset($a['has_description'])) {
$sign = (bool) $a['has_description'] ? '' : '!';
$if[] = $sign . 'dcCore::app()->ctx->feeds->feed_desc';
}
return empty($if) ?
$c :
'<?php if(' . implode(' ' . $operator . ' ', $if) . ') : ?>' . $c . '<?php endif; ?>';
}
public static function FeedIfFirst($a)
{
$ret = $a['return'] ?? 'first';
$ret = html::escapeHTML($ret);
return
'<?php if (dcCore::app()->ctx->feeds->index() == 0) { ' .
"echo '" . addslashes($ret) . "'; } ?>";
}
public static function FeedIfOdd($a)
{
$ret = $a['return'] ?? 'odd';
$ret = html::escapeHTML($ret);
return
'<?php if ((dcCore::app()->ctx->feeds->index()+1)%2 == 1) { ' .
"echo '" . addslashes($ret) . "'; } ?>";
}
public static function FeedDesc($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_desc');
}
public static function FeedOwner($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_owner');
}
public static function FeedCategory($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_title');
}
public static function FeedCategoryID($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_id');
}
public static function FeedCategoryURL($a)
{
return self::getValue($a, 'dcCore::app()->blog->url.dcCore::app()->url->getBase(\'category\').\'/\'.html::sanitizeURL(dcCore::app()->ctx->feeds->cat_url)');
}
public static function FeedCategoryShortURL($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_url');
}
public static function FeedID($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_id');
}
public static function FeedLang($a)
{
$f = dcCore::app()->tpl->getFilters($a);
return empty($a['full']) ?
'<?php echo ' . sprintf($f, 'dcCore::app()->ctx->feeds->feed_lang') . '; ?>' :
'<?php $langs = l10n::getISOcodes(); if (isset($langs[dcCore::app()->ctx->feeds->feed_lang])) { echo ' .
sprintf($f, '$langs[dcCore::app()->ctx->feeds->feed_lang]') . '; } else { echo ' .
sprintf($f, 'dcCore::app()->ctx->feeds->feed_lang') . '; } unset($langs); ?>';
}
public static function FeedName($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_name');
}
public static function FeedSiteURL($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_url');
}
public static function FeedFeedURL($a)
{
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_feed');
}
public static function FeedsHeader($a, $c)
{
return '<?php if (dcCore::app()->ctx->feeds->isStart()) : ?>' . $c . '<?php endif; ?>';
}
public static function FeedsFooter($a, $c)
{
return '<?php if (dcCore::app()->ctx->feeds->isEnd()) : ?>' . $c . '<?php endif; ?>';
}
public static function FeedsCount($a)
{
$none = 'no sources';
$one = 'one source';
$more = '%d sources';
if (isset($a['none'])) {
$none = addslashes($a['none']);
}
if (isset($a['one'])) {
$one = addslashes($a['one']);
}
if (isset($a['more'])) {
$more = addslashes($a['more']);
}
return
"<?php \$fcount = dcCore::app()->ctx->feeds->count(); \n" .
"if (\$fcount == 0) {\n" .
" printf(__('" . $none . "'),\$fcount);\n" .
"} elseif (\$fcount == 1) {\n" .
" printf(__('" . $one . "'),\$fcount);\n" .
"} else {\n" .
" printf(__('" . $more . "'),\$fcount);\n" .
'} unset($fcount); ?>';
}
public static function FeedsEntriesCount($a)
{
$none = __('no entries');
$one = __('one entry');
$more = __('%d entries');
if (isset($a['none'])) {
$none = addslashes($a['none']);
}
if (isset($a['one'])) {
$one = addslashes($a['one']);
}
if (isset($a['more'])) {
$more = addslashes($a['more']);
}
return
"<?php \$fcount = 0; \n" .
'$zc = new zoneclearFeedServer();' . "\n" .
"\$allfeeds = \$zc->getFeeds(); \n" .
"if (!\$allfeeds->isEmpty()) { \n" .
' while ($allfeeds->fetch()) { ' .
" \$fcount += (integer) \$zc->getPostsByFeed(array('feed_id'=>\$allfeeds->feed_id),true)->f(0); " .
" } \n" .
"} \n" .
"if (\$fcount == 0) {\n" .
" printf(__('" . $none . "'),\$fcount);\n" .
"} elseif (\$fcount == 1) {\n" .
" printf(__('" . $one . "'),\$fcount);\n" .
"} else {\n" .
" printf(__('" . $more . "'),\$fcount);\n" .
'} unset($allfeeds,$fcount); ?>';
}
public static function FeedEntriesCount($a)
{
$none = 'no entries';
$one = 'one entry';
$more = '%d entries';
if (isset($a['none'])) {
$none = addslashes($a['none']);
}
if (isset($a['one'])) {
$one = addslashes($a['one']);
}
if (isset($a['more'])) {
$more = addslashes($a['more']);
}
return
"<?php \$zcfs = new zoneclearFeedServer(); \n" .
"\$fcount = \$zc->getPostsByFeed(array('feed_id'=>dcCore::app()->ctx->feeds->feed_id),true)->f(0); \n" .
"if (\$fcount == 0) {\n" .
" printf(__('" . $none . "'),\$fcount);\n" .
"} elseif (\$fcount == 1) {\n" .
" printf(__('" . $one . "'),\$fcount);\n" .
"} else {\n" .
" printf(__('" . $more . "'),\$fcount);\n" .
'} unset($fcount); ?>';
}
protected static function getValue($a, $v)
{
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), $v) . '; ?>';
}
protected static function getOperator($op)
{
switch (strtolower($op)) {
case 'or':
case '||':
return '||';
case 'and':
case '&&':
default:
return '&&';
}
}
}

View File

@ -0,0 +1,102 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_RC_PATH')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Mix your blog with a feeds planet - url handler methods.
* @since 2.6
*/
class zcfsUrlHandler extends dcUrlHandlers
{
/**
* Feeds source page and update methods.
*
* @param array $args Page arguments
* @return mixed
*/
public static function zcFeedsPage($args)
{
$s = dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)));
# Not active
if (!$s->zoneclearFeedServer_active) {
self::p404();
return null;
}
# Update feeds (from ajax or other post resquest)
if ($args == '/zcfsupd' && 3 == $s->zoneclearFeedServer_bhv_pub_upd) {
$msg = '';
if (!empty($_POST['blogId']) && html::escapeJS(dcCore::app()->blog->id) == $_POST['blogId']) {
try {
$zc = new zoneclearFeedServer();
if ($zc->checkFeedsUpdate()) {
$msg = sprintf(
'<status>%s</status><message>s%</message>',
'ok',
'Feeds updated successfully'
);
}
} catch (Exception $e) {
}
}
if (empty($msg)) {
$msg = sprintf(
'<status>%s</status><message>s%</message>',
'failed',
'Failed to update feeds'
);
}
header('Content-Type: application/xml; charset=UTF-8');
echo
'<?xml version="1.0" encoding="utf-8"?> ' . "\n" .
'<response><rsp>' . "\n" .
$msg . "\n" .
'</rsp></response>';
exit(1);
# Server js
} elseif ($args == '/zcfsupd.js' && 3 == $s->zoneclearFeedServer_bhv_pub_upd) {
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates');
self::serveDocument(
'zcfsupd.js',
'text/javascript',
false,
false
);
# Server feeds description page
} elseif (in_array($args, ['', '/']) && $s->zoneclearFeedServer_pub_active) {
$tplset = dcCore::app()->themes->moduleInfo(dcCore::app()->blog->settings->system->theme, 'tplset');
$path = __DIR__ . '/default-templates/';
if (!empty($tplset) && is_dir($path . $tplset)) {
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), $path . $tplset);
} else {
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), $path . DC_DEFAULT_TPLSET);
}
self::serveDocument('zcfeeds.html');
}
# Unknow
else {
self::p404();
}
return null;
}
}

View File

@ -1,412 +0,0 @@
<?php
/**
* @brief zoneclearFeedServer, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis, BG, Pierre Van Glabeke
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Feeds server - feeds list methods
* @since 2.6
* @see adminGenericList for more info
*/
class zcfsFeedsList extends adminGenericList
{
private $zc = null;
public function feedsDisplay($page, $nb_per_page, $enclose_block = '', $filter = false)
{
if ($this->rs->isEmpty()) {
if ($filter) {
echo '<p><strong>' . __('No feeds matches the filter') . '</strong></p>';
} else {
echo '<p><strong>' . __('No feeds') . '</strong></p>';
}
} else {
$this->zc = new zoneclearFeedServer();
$pager = new dcPager($page, $this->rs_count, $nb_per_page, 10);
$entries = [];
if (isset($_REQUEST['feeds'])) {
foreach ($_REQUEST['feeds'] as $v) {
$entries[(int) $v] = true;
}
}
$html_block = '<div class="table-outer">' .
'<table>' .
'<caption>' . (
$filter ?
sprintf(__('List of %s feeds matching the filter.'), $this->rs_count) :
sprintf(__('List of feeds (%s)'), $this->rs_count)
) . '</caption>';
$cols = [
'title' => '<th colspan="2" class="first">' . __('Name') . '</th>',
'desc' => '<th scope="col">' . __('Feed') . '</th>',
'period' => '<th scope="col">' . __('Frequency') . '</th>',
'update' => '<th scope="col">' . __('Last update') . '</th>',
'entries' => '<th scope="col">' . __('Entries') . '</th>',
'status' => '<th scope="col">' . __('Status') . '</th>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsFeedsListHeader', $this->rs, $cols);
$this->userColumns('zcfs_feeds', $cols);
$html_block .= '<tr>' . implode(iterator_to_array($cols)) . '</tr>%s</table>%s</div>';
if ($enclose_block) {
$html_block = sprintf($enclose_block, $html_block);
}
echo $pager->getLinks();
$blocks = explode('%s', $html_block);
echo $blocks[0];
while ($this->rs->fetch()) {
echo $this->feedsLine(isset($entries[$this->rs->feed_id]));
}
echo $blocks[1];
echo $blocks[2];
echo $pager->getLinks();
}
}
private function feedsLine($checked)
{
$combo_status = zoneclearFeedServer::getAllStatus();
$combo_upd_int = zoneclearFeedServer::getAllUpdateInterval();
$status = $this->rs->feed_status ?
'<img src="images/check-on.png" alt="enable" />' :
'<img src="images/check-off.png" alt="disable" />';
$entries_count = $this->zc->getPostsByFeed(['feed_id' => $this->rs->feed_id], true)->f(0);
$shunk_feed = $this->rs->feed_feed;
if (strlen($shunk_feed) > 83) {
$shunk_feed = substr($shunk_feed, 0, 50) . '...' . substr($shunk_feed, -20);
}
$url = dcCore::app()->adminurl->get('admin.plugin.' . basename(dirname('../' . __DIR__)), ['part' => 'feed', 'feed_id' => $this->rs->feed_id]);
$cols = [
'check' => '<td class="nowrap minimal">' .
form::checkbox(['feeds[]'], $this->rs->feed_id, ['checked' => $checked]) .
'</td>',
'title' => '<td class="nowrap" scope="row">' .
'<a href="' . $url . '#feed" title="' . __('Edit') . '">' . html::escapeHTML($this->rs->feed_name) . '</a>' .
'</td>',
'desc' => '<td class="nowrap maximal">' .
'<a href="' . $this->rs->feed_feed . '" title="' . html::escapeHTML($this->rs->feed_desc) . '">' . html::escapeHTML($shunk_feed) . '</a>' .
'</td>',
'period' => '<td class="nowrap minimal count">' .
array_search($this->rs->feed_upd_int, $combo_upd_int) .
'</td>',
'update' => '<td class="nowrap minimal count">' .
(
$this->rs->feed_upd_last < 1 ?
__('never') :
dt::str(__('%Y-%m-%d %H:%M'), (int) $this->rs->feed_upd_last, dcCore::app()->auth->getInfo('user_tz'))
) . '</td>',
'entries' => '<td class="nowrap minimal count">' .
(
$entries_count ?
'<a href="' . $url . '#entries" title="' . __('View entries') . '">' . $entries_count . '</a>' :
$entries_count
) . '</td>',
'status' => '<td class="nowrap minimal status">' . $status . '</td>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsFeedsListValue', $this->rs, $cols);
$this->userColumns('zcfs_feeds', $cols);
return
'<tr class="line ' . ($this->rs->feed_status ? '' : 'offline ') . '" id="p' . $this->rs->feed_id . '">' .
implode(iterator_to_array($cols)) .
'</tr>';
}
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Feeds server - Posts list methods
* @since 2.6
* @see adminGenericList for more info
*/
class zcfsEntriesList extends adminGenericList
{
public function display($page, $nb_per_page, $base_url, $enclose_block = '', $filter = false)
{
if ($this->rs->isEmpty()) {
echo '<p><strong>' . (
$filter ?
__('No entries matches the filter') :
__('No entries')
) . '</strong></p>';
} else {
$pager = new dcPager($page, $this->rs_count, $nb_per_page, 10);
$pager->base_url = $base_url;
$entries = [];
if (isset($_REQUEST['feeds'])) {
foreach ($_REQUEST['feeds'] as $v) {
$entries[(int) $v] = true;
}
}
$html_block = '<div class="table-outer clear">' .
'<table>' .
'<caption>' . (
$filter ?
sprintf(__('List of %s entries matching the filter.'), $this->rs_count) :
sprintf(__('List of entries (%s)'), $this->rs_count)
) . '</caption>';
$cols = [
'title' => '<th scope="col" colspan="2" class="first">' . __('Title') . '</th>',
'date' => '<th scope="col">' . __('Date') . '</th>',
'author' => '<th scope="col">' . __('Author') . '</th>',
'category' => '<th scope="col">' . __('Category') . '</th>',
'status' => '<th scope="col">' . __('Status') . '</th>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsPostListHeader', $this->rs, $cols);
$this->userColumns('zcfs_entries', $cols);
$html_block .= '<tr>' . implode(iterator_to_array($cols)) . '</tr>%s</table></div>';
if ($enclose_block) {
$html_block = sprintf($enclose_block, $html_block);
}
echo $pager->getLinks();
$blocks = explode('%s', $html_block);
echo $blocks[0];
while ($this->rs->fetch()) {
echo $this->postLine();
}
echo $blocks[1];
echo $pager->getLinks();
}
}
private function postLine()
{
$cat_link = dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_CATEGORIES]), dcCore::app()->blog->id) ?
'<a href="category.php?id=%s" title="' . __('Edit category') . '">%s</a>'
: '%2$s';
$cat_title = $this->rs->cat_title ?
sprintf($cat_link, $this->rs->cat_id, html::escapeHTML($this->rs->cat_title))
: __('None');
$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
$img_status = '';
$sts_class = '';
switch ($this->rs->post_status) {
case 1:
$img_status = sprintf($img, __('Published'), 'check-on.png');
$sts_class = 'sts-online';
break;
case 0:
$img_status = sprintf($img, __('Unpublished'), 'check-off.png');
$sts_class = 'sts-offline';
break;
case -1:
$img_status = sprintf($img, __('Scheduled'), 'scheduled.png');
$sts_class = 'sts-scheduled';
break;
case -2:
$img_status = sprintf($img, __('Pending'), 'check-wrn.png');
$sts_class = 'sts-pending';
break;
}
$res = '<tr class="line ' . ($this->rs->post_status != 1 ? 'offline ' : '') . $sts_class . '"' .
' id="p' . $this->rs->post_id . '">';
$cols = [
'check' => '<td class="nowrap minimal">' .
form::checkbox(['entries[]'], $this->rs->post_id, '', '', '', !$this->rs->isEditable()) . '</td>',
'title' => '<td scope="row" class="maximal"><a href="' .
dcCore::app()->getPostAdminURL($this->rs->post_type, $this->rs->post_id) . '" ' .
'title="' . html::escapeHTML($this->rs->getURL()) . '">' .
html::escapeHTML(trim(html::clean($this->rs->post_title))) . '</a></td>',
'date' => '<td class="nowrap count">' . dt::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->post_dt) . '</td>',
'author' => '<td class="nowrap">' . html::escapeHTML($this->rs->user_id) . '</td>',
'category' => '<td class="nowrap">' . $cat_title . '</td>',
'status' => '<td class="nowrap status">' . $img_status . '</td>',
];
$cols = new ArrayObject($cols);
dcCore::app()->callBehavior('adminZcfsPostListValue', $this->rs, $cols);
$this->userColumns('zcfs_entries', $cols);
$res .= implode(iterator_to_array($cols));
$res .= '</tr>';
return $res;
}
}
/**
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
* @brief Feeds server - Posts list filters methods
* @since 2.20
* @see adminGenericFilter for more info
*/
class adminZcfsPostFilter extends adminGenericFilter
{
public function __construct()
{
parent::__construct(dcCore::app(), 'zcfs_entries');
$filters = new arrayObject([
dcAdminFilters::getPageFilter(),
$this->getPostUserFilter(),
$this->getPostCategoriesFilter(),
$this->getPostStatusFilter(),
$this->getPostMonthFilter(),
]);
# --BEHAVIOR-- adminPostFilter
dcCore::app()->callBehavior('adminZcfsPostFilter', $filters);
$filters = $filters->getArrayCopy();
$this->add($filters);
}
/**
* Posts users select
*/
public function getPostUserFilter(): ?dcAdminFilter
{
$users = null;
try {
$users = dcCore::app()->blog->getPostsUsers();
if ($users->isEmpty()) {
return null;
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return null;
}
$combo = dcAdminCombos::getUsersCombo($users);
dcUtils::lexicalKeySort($combo);
return (new dcAdminFilter('user_id'))
->param()
->title(__('Author:'))
->options(array_merge(
['-' => ''],
$combo
))
->prime(true);
}
/**
* Posts categories select
*/
public function getPostCategoriesFilter(): ?dcAdminFilter
{
$categories = null;
try {
$categories = dcCore::app()->blog->getCategories();
if ($categories->isEmpty()) {
return null;
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return null;
}
$combo = [
'-' => '',
__('(No cat)') => 'NULL',
];
while ($categories->fetch()) {
$combo[
str_repeat('&nbsp;', ($categories->level - 1) * 4) .
html::escapeHTML($categories->cat_title) . ' (' . $categories->nb_post . ')'
] = $categories->cat_id;
}
return (new dcAdminFilter('cat_id'))
->param()
->title(__('Category:'))
->options($combo)
->prime(true);
}
/**
* Posts status select
*/
public function getPostStatusFilter(): dcAdminFilter
{
return (new dcAdminFilter('status'))
->param('post_status')
->title(__('Status:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getPostStatusesCombo()
));
}
/**
* Posts by month select
*/
public function getPostMonthFilter(): ?dcAdminFilter
{
$dates = null;
try {
$dates = dcCore::app()->blog->getDates(['type' => 'month']);
if ($dates->isEmpty()) {
return null;
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return null;
}
return (new dcAdminFilter('month'))
->param('post_month', function ($f) { return substr($f[0], 4, 2); })
->param('post_year', function ($f) { return substr($f[0], 0, 4); })
->title(__('Month:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getDatesCombo($dates)
));
}
}

View File

@ -270,7 +270,7 @@ if (!dcCore::app()->blog->settings->__get(basename(__DIR__))->zoneclearFeedServe
} }
# filters # filters
$post_filter = new adminZcfsPostFilter(); $post_filter = new zcfsPostFilter();
$post_filter->add('part', 'feed'); $post_filter->add('part', 'feed');
$post_filter->add('feed_id', $feed_id); $post_filter->add('feed_id', $feed_id);
$params = $post_filter->params(); $params = $post_filter->params();
@ -487,7 +487,7 @@ if (!dcCore::app()->blog->settings->__get(basename(__DIR__))->zoneclearFeedServe
############################################################ ############################################################
} else { } else {
# actions # actions
$feeds_actions_page = new zcfsFeedsActionsPage( $feeds_actions_page = new zcfsFeedsActions(
'plugin.php', 'plugin.php',
['p' => basename(__DIR__), 'part' => 'feeds'] ['p' => basename(__DIR__), 'part' => 'feeds']
); );