use namespace
This commit is contained in:
parent
b7affac99d
commit
ef04d66d44
35 changed files with 4781 additions and 3535 deletions
|
@ -7,7 +7,7 @@
|
|||
|
||||
$opts = getopt('d:c:b:u:h');
|
||||
|
||||
function zchelp($status = 0)
|
||||
function zchelp(string|int $status = 0): void
|
||||
{
|
||||
echo
|
||||
"Options: \n" .
|
||||
|
@ -33,7 +33,7 @@ if (isset($opts['d'])) {
|
|||
$dc_root = $_SERVER['DC_ROOT'];
|
||||
}
|
||||
|
||||
if (isset($opts['c'])) {
|
||||
if (isset($opts['c']) && is_string($opts['c'])) {
|
||||
$dc_conf = realpath($opts['c']);
|
||||
} elseif (isset($_SERVER['DC_RC_PATH'])) {
|
||||
$dc_conf = realpath($_SERVER['DC_RC_PATH']);
|
||||
|
@ -55,7 +55,7 @@ if (!$dc_conf || !is_readable($dc_conf)) {
|
|||
zchelp(1);
|
||||
}
|
||||
|
||||
if (!$blog_id) {
|
||||
if (!$blog_id || !is_string($blog_id)) {
|
||||
fwrite(STDERR, "Blog ID is not defined\n\n");
|
||||
zchelp(1);
|
||||
}
|
||||
|
@ -69,23 +69,21 @@ unset($blog_id);
|
|||
require $dc_root . '/inc/prepend.php';
|
||||
unset($dc_root);
|
||||
|
||||
dcCore::app()->setBlog(DC_BLOG_ID);
|
||||
if (dcCore::app()->blog->id == null) {
|
||||
dcCore::app()->setBlog(is_string(DC_BLOG_ID) ? DC_BLOG_ID : '');
|
||||
if (is_null(dcCore::app()->blog) || dcCore::app()->blog->id == null) {
|
||||
fwrite(STDERR, "Blog is not defined\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!isset($opts['u']) || !dcCore::app()->auth->checkUser($opts['u'])) {
|
||||
if (!isset($opts['u']) || is_null(dcCore::app()->auth) || !dcCore::app()->auth->checkUser(is_string($opts['u']) ? $opts['u'] : '')) {
|
||||
fwrite(STDERR, "Unable to set user\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dcCore::app()->plugins->loadModules(DC_PLUGINS_ROOT);
|
||||
|
||||
dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
|
||||
|
||||
try {
|
||||
$zc = new zoneclearFeedServer();
|
||||
$zc = Dotclear\Plugin\zoneclearFeedServer\ZoneclearFeedServer::instance();
|
||||
$zc->checkFeedsUpdate();
|
||||
} catch (Exception $e) {
|
||||
fwrite(STDERR, $e->getMessage() . "\n");
|
||||
|
|
|
@ -1,243 +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 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',
|
||||
]) . ' '
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,87 +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_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)
|
||||
{
|
||||
dcCore::app()->__set('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::publicDocumentV2();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
|
@ -1,3 +1,8 @@
|
|||
$(function(){
|
||||
/*global $, dotclear */
|
||||
'use strict';
|
||||
|
||||
$(() => {
|
||||
$('.checkboxes-helpers').each(function(){dotclear.checkboxesHelpers(this);});
|
||||
dotclear.condSubmit('#form-feeds td input[type=checkbox]', '#form-feeds #feeds-action');
|
||||
dotclear.condSubmit('#form-entries td input[type=checkbox]', '#form-entries #feed-action');
|
||||
});
|
|
@ -1,7 +1,10 @@
|
|||
$(function(){
|
||||
/*global $, dotclear */
|
||||
'use strict';
|
||||
|
||||
$(() => {
|
||||
/* toogle admin form sidebar */
|
||||
$('#zcfs h5').toggleWithLegend(
|
||||
$('#zcfs').children().not('h5'),
|
||||
{cookie:'dcx_zcfs_admin_form_sidebar',legend_click:true}
|
||||
{user_pref:'dcx_zcfs_admin_form_sidebar',legend_click:true}
|
||||
);
|
||||
});
|
160
locales/fr/main.lang.php
Normal file
160
locales/fr/main.lang.php
Normal file
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Dotclear
|
||||
*
|
||||
* @copyright Olivier Meunier & Association Dotclear
|
||||
* @copyright GPL-2.0-only
|
||||
*/
|
||||
#
|
||||
# DOT NOT MODIFY THIS FILE !
|
||||
#
|
||||
|
||||
use Dotclear\Helper\L10n;
|
||||
|
||||
L10n::$locales['List of feeds'] = 'Liste des sources';
|
||||
L10n::$locales['Feed properties update'] = 'Mise à jour de flux';
|
||||
L10n::$locales['Feed named "%s" point to "%s" has been updated by "%s"'] = 'Le flux nommé "%s" pointant vers "%s" a été mis à jour par "%s"';
|
||||
L10n::$locales['Feed creation'] = 'Création de flux';
|
||||
L10n::$locales['A new feed named "%s" point to "%s" was added by "%s"'] = 'Un nouveau flux nommé "%s" pointant vers "%s" a été ajouté par "%s"';
|
||||
L10n::$locales['Feed status'] = 'Satut de flux';
|
||||
L10n::$locales['Feed named "%s" point to "%s" has been set to "%s"'] = 'Le flux nommé "%s" pointant vers "%s" a été marqué comme "%s"';
|
||||
L10n::$locales['Feed deletion'] = 'Suppression de flux';
|
||||
L10n::$locales['Feed named "%s" point to "%s" has been deleted by "%s"'] = 'Le flux nommé "%s" pointant vers "%s" a été supprimé par "%s"';
|
||||
L10n::$locales['Check feed update'] = 'Vérification de flux';
|
||||
L10n::$locales['Feed named "%s" has been updated automatically'] = 'Le flux nommé "%s" pointant vers "%s" a été vérifié automatiquement';
|
||||
L10n::$locales['%s feed disabled'] = [
|
||||
'%s flux désactivé',
|
||||
'%s flux désactivés',
|
||||
];
|
||||
L10n::$locales['Feeds server: Feeds'] = 'Serveur de flux : Flux';
|
||||
L10n::$locales['Feed'] = 'Flux';
|
||||
L10n::$locales['Feeds server: Entries'] = 'Serveur de flux : Billets';
|
||||
L10n::$locales['Feed server'] = 'Serveur de flux';
|
||||
L10n::$locales['feeds per page'] = 'flux par page';
|
||||
L10n::$locales['edit feed'] = 'Modifier le flux';
|
||||
L10n::$locales['Edit this feed'] = 'Modifier ce flux';
|
||||
L10n::$locales['Feed source'] = 'Source du flux';
|
||||
L10n::$locales['feed URL'] = 'URL du fil';
|
||||
L10n::$locales['site URL'] = 'URL du site';
|
||||
L10n::$locales['Update date'] = 'Date de mise à jour';
|
||||
L10n::$locales['Disabled'] = 'Désactivé';
|
||||
L10n::$locales['Enabled'] = 'Activé';
|
||||
L10n::$locales['Every hour'] = 'Toutes les heures';
|
||||
L10n::$locales['Every two hours'] = 'Toutes les deux heures';
|
||||
L10n::$locales['Two times per day'] = 'Deux fois par jour';
|
||||
L10n::$locales['Every day'] = 'Chaque jour';
|
||||
L10n::$locales['Every two days'] = 'Tous les deux jours';
|
||||
L10n::$locales['Keep source case'] = 'Garder la casse de la source';
|
||||
L10n::$locales['First upper case'] = 'Premier caractère en majuscule';
|
||||
L10n::$locales['All lower case'] = 'Tout en minuscule';
|
||||
L10n::$locales['All upper case'] = 'Tout en majuscule';
|
||||
L10n::$locales['Disable'] = 'Désactiver';
|
||||
L10n::$locales['Before display'] = 'Avant l\'affichage';
|
||||
L10n::$locales['After display'] = 'Après l\'affichage';
|
||||
L10n::$locales['Through Ajax'] = 'À travers Ajax';
|
||||
L10n::$locales['Configuration has been successfully updated.'] = 'La configuration a été mise à jour avec succés.';
|
||||
L10n::$locales['Dotclear cache is not writable or not well configured!'] = 'Le cache de Dotclear n\'est pas accessible en écriture ou n\'est pas configuré !';
|
||||
L10n::$locales['View the public list of feeds'] = 'Voir la page publique de la liste des flux';
|
||||
L10n::$locales['Enable plugin'] = 'Activer le plugin';
|
||||
L10n::$locales['Status of new posts:'] = 'Status des nouveaux billets :';
|
||||
L10n::$locales['Owner of entries created by the feed server:'] = 'Propriétaire des billets créés par le serveur de flux :';
|
||||
L10n::$locales['How to transform imported tags:'] = 'Comment tranformer la casse des mots-clés importés :';
|
||||
L10n::$locales['Update feeds on public side:'] = 'Mettre à jour les flux depuis la partie publique :';
|
||||
L10n::$locales['Number of feeds to update at one time:'] = 'Nombre de flux mis à jour à la fois :';
|
||||
L10n::$locales['Keep active empty feeds'] = 'Garder actif les flux vides';
|
||||
L10n::$locales['Enable public page'] = 'Activer la page publique';
|
||||
L10n::$locales['Redirect to original post on:'] = 'Rediriger vers le billet original sur :';
|
||||
L10n::$locales['Show full content on:'] = 'Afficher le contenu complet sur :';
|
||||
L10n::$locales['Feeds'] = 'Flux de syndication';
|
||||
L10n::$locales['Feeds server'] = 'Serveur de flux';
|
||||
L10n::$locales['Back to feeds list'] = 'Retour à la liste des flux';
|
||||
L10n::$locales['Feeds actions'] = 'Actions sur les flux';
|
||||
L10n::$locales['Change update interval'] = 'Changer l\'interval de mise à jour';
|
||||
L10n::$locales['Disable feed update'] = 'Désactiver la mise à jour du flux';
|
||||
L10n::$locales['Enable feed update'] = 'Activer la mise à jour du flux';
|
||||
L10n::$locales['Reset last update'] = 'Remettre à zéro le chronomètre de mise à jour';
|
||||
L10n::$locales['Update (check) feed'] = 'Mettre à jour (vérifier) le flux';
|
||||
L10n::$locales['Delete related posts'] = 'Effacer les billets liés';
|
||||
L10n::$locales['Delete feed (without related posts)'] = 'Effacer le flux (sans effacer les billets liés)';
|
||||
L10n::$locales['No feeds selected'] = 'Aucun flux selectionné';
|
||||
L10n::$locales['Entries have been successfully deleted.'] = 'Les billets ont été effacé avec succès.';
|
||||
L10n::$locales['%d feed has been successfully updated.'] = [
|
||||
'%s flux a été mis à jour.',
|
||||
'%s flux ont été mis à jour.',
|
||||
];
|
||||
L10n::$locales['Last update of %s feed successfully reseted.'] = [
|
||||
'La date de dernière mise à jour de %s flux a été remis à zéro.',
|
||||
'Les date de dernière mise à jour de %s flux ont été remis à zéro.',
|
||||
];
|
||||
L10n::$locales['Category of %s feed successfully changed.'] = [
|
||||
'La catégorie de %s flux a été changé.',
|
||||
'Les catégories de %s flux ont été changé.',
|
||||
];
|
||||
L10n::$locales['Update frequency of %s feed successfully changed.'] = [
|
||||
'La fréquence de mise à jour de %s flux a été changé.',
|
||||
'Les fréquences de mise à jour de %s flux ont été changé.',
|
||||
];
|
||||
L10n::$locales['Change update frequency for this selection'] = 'Changer la fréquence de mise à jour pour la selection';
|
||||
L10n::$locales['Frequency:'] = 'Fréquence :';
|
||||
L10n::$locales['No feeds matches the filter'] = 'Aucun flux correspondant au filtre.';
|
||||
L10n::$locales['No feeds'] = 'Aucun flux';
|
||||
L10n::$locales['List of %s feeds matching the filter.'] = 'Liste des %s flux correspondant au filtre.';
|
||||
L10n::$locales['List of feeds. (%s)'] = 'Liste des flux. (%s)';
|
||||
L10n::$locales['enabled'] = 'activé';
|
||||
L10n::$locales['disabled'] = 'désactivé';
|
||||
L10n::$locales['never'] = 'jamais';
|
||||
L10n::$locales['View entries'] = 'Voir les billets';
|
||||
L10n::$locales['Module is not wel configured'] = 'Le module n\'est pas configuré correctement';
|
||||
L10n::$locales['Feeds list'] = 'Liste de flux';
|
||||
L10n::$locales['New feed'] = 'Nouveau flux';
|
||||
L10n::$locales['Selected feeds action:'] = 'Action sur les flux sélectionnés :';
|
||||
L10n::$locales['Record with same feed URL already exists.'] = 'Un enregistrement avec la même URL de flux existe déjà.';
|
||||
L10n::$locales['You must provide a name.'] = 'Vous devez indiquer un nom.';
|
||||
L10n::$locales['You must provide an owner.'] = 'Vous devez indiquer un propriétaire.';
|
||||
L10n::$locales['You must provide valid site URL.'] = 'Vous devez donner une URL de site valide.';
|
||||
L10n::$locales['You must provide valid feed URL.'] = 'Vous devez donner une URL de flux valide.';
|
||||
L10n::$locales['You must provide valid category.'] = 'Vous devez donner une catégorie valide.';
|
||||
L10n::$locales['Failed to save feed.'] = 'Impossible de sauvegarder le flux.';
|
||||
L10n::$locales['Feed successfully created.'] = 'Flux créé avec succcès.';
|
||||
L10n::$locales['Edit feed'] = 'Edition de flux';
|
||||
L10n::$locales['Edit feed "%s"'] = 'Modifier le flux "%s"';
|
||||
L10n::$locales['Feed information'] = 'Information sur le flux';
|
||||
L10n::$locales['Owner:'] = 'Propriétaire :';
|
||||
L10n::$locales['Site URL:'] = 'URL du site :';
|
||||
L10n::$locales['Tweeter or Identica ident:'] = 'Identifiant Twiiter ou Identi.ca :';
|
||||
L10n::$locales['Local settings'] = 'Paramètres locaux';
|
||||
L10n::$locales['Update:'] = 'Mise à jour :';
|
||||
L10n::$locales['Import tags from feed'] = 'Importer les tags depuis le flux';
|
||||
L10n::$locales['This feed does not exist.'] = 'Ce flux n\'existe pas.';
|
||||
L10n::$locales['next feed'] = 'flux suivant';
|
||||
L10n::$locales['previous feed'] = 'flux précédent';
|
||||
L10n::$locales['No entries matches the filter'] = 'Aucun billet correspondant au filtre.';
|
||||
L10n::$locales['No entries'] = 'Aucun billet';
|
||||
L10n::$locales['List of entries. (%s)'] = 'Liste des billets. (%s)';
|
||||
L10n::$locales['Original post on <a href="%s">%s</a>'] = 'Billet original sur <a href="%s">%s</a>';
|
||||
L10n::$locales['Read more details about this feed'] = 'Lire plus de détails à propos de ce flux';
|
||||
L10n::$locales['Feeds server: sources'] = 'Serveur de flux : les sources';
|
||||
L10n::$locales['List sources of feeds'] = 'Liste des sources du flux';
|
||||
L10n::$locales['Feeds sources'] = 'Sources des flux';
|
||||
L10n::$locales['Create date'] = 'Date de création';
|
||||
L10n::$locales['Limit:'] = 'Limite :';
|
||||
L10n::$locales['Link to the list of sources:'] = 'Lien vers la liste des sources :';
|
||||
L10n::$locales['All sources'] = 'Toutes les sources';
|
||||
L10n::$locales['Feeds server: numbers'] = 'Serveur de flux : les chiffres';
|
||||
L10n::$locales['Show some numbers about feeds'] = 'Afficher quelques chiffres à propose du flux';
|
||||
L10n::$locales['Feeds numbers'] = 'Le flux en chiffres';
|
||||
L10n::$locales['Show feeds count'] = 'Afficher le nombre de flux';
|
||||
L10n::$locales['Title for feeds count:'] = 'Titre pour le nombre de flux :';
|
||||
L10n::$locales['Feeds:'] = 'Flux :';
|
||||
L10n::$locales['Show entries count'] = 'Afficher le nombre de billets';
|
||||
L10n::$locales['Title for entries count:'] = 'Titre pour le nombre de billets :';
|
||||
L10n::$locales['Entries:'] = 'Billets :';
|
||||
L10n::$locales['one source'] = 'une source';
|
||||
L10n::$locales['no sources'] = 'aucune source';
|
||||
L10n::$locales['one entry'] = 'une publication';
|
||||
L10n::$locales['no entries'] = 'aucune publication';
|
||||
L10n::$locales['Entries pages'] = 'Pages des billets';
|
||||
L10n::$locales['Tags pages'] = 'Pages des mots-clés';
|
||||
L10n::$locales['Archives pages'] = 'Pages des archives';
|
||||
L10n::$locales['Category pages'] = 'Pages de catégories';
|
||||
L10n::$locales['Mix your blog with a feeds planet'] = 'Mixer votre blog avec un planet';
|
|
@ -1,399 +1,560 @@
|
|||
# Language: Français
|
||||
# Module: zoneclearFeedServer - 2022.12.11.00001
|
||||
# Date: 2023-05-07 22:36:31
|
||||
# Author: Jean-Christian Denis
|
||||
# Translated with translater 2023.04.23
|
||||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Project-Id-Version: zoneclearFeedServer 2022.11.26\n"
|
||||
"Project-Id-Version: zoneclearFeedServer 2022.12.11.00001\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: 2022-12-10T22:19:59+00:00\n"
|
||||
"PO-Revision-Date: 2023-05-07T22:36:31+00:00\n"
|
||||
"Last-Translator: Jean-Christian Denis\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
msgid "Feeds server"
|
||||
msgstr "Serveur de flux"
|
||||
|
||||
msgid "Disable"
|
||||
msgstr "Désactiver"
|
||||
|
||||
msgid "Before display"
|
||||
msgstr "Avant l'affichage"
|
||||
|
||||
msgid "After display"
|
||||
msgstr "Après l'affichage"
|
||||
|
||||
msgid "Through Ajax"
|
||||
msgstr "À travers Ajax"
|
||||
|
||||
msgid "Keep source case"
|
||||
msgstr "Garder la casse de la source"
|
||||
|
||||
msgid "First upper case"
|
||||
msgstr "Premier caractère en majuscule"
|
||||
|
||||
msgid "All lower case"
|
||||
msgstr "Tout en minuscule"
|
||||
|
||||
msgid "All upper case"
|
||||
msgstr "Tout en majuscule"
|
||||
|
||||
msgid "Dotclear cache is not writable or not well configured!"
|
||||
msgstr "Le cache de Dotclear n'est pas accessible en écriture ou n'est pas configuré !"
|
||||
|
||||
msgid "Enable plugin"
|
||||
msgstr "Activer le plugin"
|
||||
|
||||
msgid "View the public list of feeds"
|
||||
msgstr "Voir la page publique de la liste des flux"
|
||||
|
||||
msgid "Rules"
|
||||
msgstr "Règles"
|
||||
|
||||
msgid "Status of new posts:"
|
||||
msgstr "Status des nouveaux billets :"
|
||||
|
||||
msgid "Owner of entries created by zoneclearFeedServer:"
|
||||
msgstr "Propriétaire des billets créés par zoneclearFeedServer :"
|
||||
|
||||
msgid "How to transform imported tags:"
|
||||
msgstr "Comment tranformer la casse des mots-clés importés :"
|
||||
|
||||
msgid "Update feeds on public side:"
|
||||
msgstr "Mettre à jour les flux depuis la partie publique :"
|
||||
|
||||
msgid "Update %s feed(s) at a time."
|
||||
msgstr "Mettre à jour %s flux à la fois."
|
||||
|
||||
msgid "Keep active empty feeds"
|
||||
msgstr "Garder actif les flux vides"
|
||||
|
||||
msgid "Enable public page"
|
||||
msgstr "Activer la page publique"
|
||||
|
||||
msgid "Redirect to original post on:"
|
||||
msgstr "Rediriger vers le billet original sur :"
|
||||
|
||||
msgid "Show full content on:"
|
||||
msgstr "Afficher le contenu complet sur :"
|
||||
|
||||
#: default-templates/currywurst/zcfeeds.html:4
|
||||
#: default-templates/mustek/zcfeeds.html:4
|
||||
#: src/Frontend.php:52
|
||||
msgid "List of feeds"
|
||||
msgstr "Liste des sources"
|
||||
|
||||
msgid "Feeds server: sources"
|
||||
msgstr "Serveur de flux : les sources"
|
||||
|
||||
msgid "List sources of feeds"
|
||||
msgstr "Liste des sources du flux"
|
||||
|
||||
msgid "Feeds sources"
|
||||
msgstr "Sources des flux"
|
||||
|
||||
msgid "Create date"
|
||||
msgstr "Date de création"
|
||||
|
||||
msgid "Limit:"
|
||||
msgstr "Limite :"
|
||||
|
||||
msgid "Link to the list of sources:"
|
||||
msgstr "Lien vers la liste des sources :"
|
||||
|
||||
msgid "All sources"
|
||||
msgstr "Toutes les sources"
|
||||
|
||||
msgid "Feeds server: numbers"
|
||||
msgstr "Serveur de flux : les chiffres"
|
||||
|
||||
msgid "Show some numbers about feeds"
|
||||
msgstr "Afficher quelques chiffres à propose du flux"
|
||||
|
||||
msgid "Feeds numbers"
|
||||
msgstr "Le flux en chiffres"
|
||||
|
||||
msgid "Show feeds count"
|
||||
msgstr "Afficher le nombre de flux"
|
||||
|
||||
msgid "Title for feeds count:"
|
||||
msgstr "Titre pour le nombre de flux :"
|
||||
|
||||
msgid "Feeds:"
|
||||
msgstr "Flux :"
|
||||
|
||||
msgid "Show entries count"
|
||||
msgstr "Afficher le nombre de billets"
|
||||
|
||||
msgid "Title for entries count:"
|
||||
msgstr "Titre pour le nombre de billets :"
|
||||
|
||||
msgid "Entries:"
|
||||
msgstr "Billets :"
|
||||
|
||||
msgid "one source"
|
||||
msgstr "une source"
|
||||
|
||||
msgid "no sources"
|
||||
msgstr "aucune source"
|
||||
|
||||
msgid "one entry"
|
||||
msgstr "une publication"
|
||||
|
||||
msgid "no entries"
|
||||
msgstr "aucune publication"
|
||||
|
||||
msgid "feed creation"
|
||||
msgstr "création d'un flux"
|
||||
|
||||
msgid "A new feed named \"%s\" point to \"%s\" was added by \"%s\""
|
||||
msgstr "Un nouveau flux nommé \"%s\" pointant vers \"%s\" a été ajouté par \"%s\""
|
||||
|
||||
msgid "updating feed info"
|
||||
msgstr "mise à jour des informations du flux (administration)"
|
||||
#: src/ActivityReportActions.php:36
|
||||
msgid "Feed properties update"
|
||||
msgstr "Mise à jour de flux"
|
||||
|
||||
#: src/ActivityReportActions.php:37
|
||||
msgid "Feed named \"%s\" point to \"%s\" has been updated by \"%s\""
|
||||
msgstr "Le flux nommé \"%s\" pointant vers \"%s\" a été mis à jour par \"%s\""
|
||||
|
||||
msgid "updating feed records"
|
||||
msgstr "mise à jour des enregistrements du flux (automatique)"
|
||||
#: src/ActivityReportActions.php:63
|
||||
msgid "Feed creation"
|
||||
msgstr "Création de flux"
|
||||
|
||||
msgid "Records of the feed named \"%s\" have been updated automatically"
|
||||
msgstr "Les enregistrements du flux nommé \"%s\" ont été automatiquement mis à jour"
|
||||
#: src/ActivityReportActions.php:64
|
||||
msgid "A new feed named \"%s\" point to \"%s\" was added by \"%s\""
|
||||
msgstr "Un nouveau flux nommé \"%s\" pointant vers \"%s\" a été ajouté par \"%s\""
|
||||
|
||||
msgid "feed deletion"
|
||||
msgstr "suppression d'un flux"
|
||||
|
||||
msgid "Feed named \"%s\" point to \"%s\" has been deleted by \"%s\""
|
||||
msgstr "Le flux nommé \"%s\" pointant vers \"%s\" a été supprimé par \"%s\""
|
||||
|
||||
msgid "feed status"
|
||||
msgstr "status d'un flux"
|
||||
#: src/ActivityReportActions.php:83
|
||||
msgid "Feed status"
|
||||
msgstr "Satut de flux"
|
||||
|
||||
#: src/ActivityReportActions.php:84
|
||||
msgid "Feed named \"%s\" point to \"%s\" has been set to \"%s\""
|
||||
msgstr "Le flux nommé \"%s\" pointant vers \"%s\" a été marqué comme \"%s\""
|
||||
|
||||
msgid "Update date"
|
||||
msgstr "Date de mise à jour"
|
||||
#: src/ActivityReportActions.php:105
|
||||
msgid "Feed deletion"
|
||||
msgstr "Suppression de flux"
|
||||
|
||||
#: src/ActivityReportActions.php:106
|
||||
msgid "Feed named \"%s\" point to \"%s\" has been deleted by \"%s\""
|
||||
msgstr "Le flux nommé \"%s\" pointant vers \"%s\" a été supprimé par \"%s\""
|
||||
|
||||
#: src/ActivityReportActions.php:132
|
||||
msgid "Check feed update"
|
||||
msgstr "Vérification de flux"
|
||||
|
||||
#: src/ActivityReportActions.php:133
|
||||
msgid "Feed named \"%s\" has been updated automatically"
|
||||
msgstr "Le flux nommé \"%s\" pointant vers \"%s\" a été vérifié automatiquement"
|
||||
|
||||
#: src/BackendBehaviors.php:68
|
||||
msgid "%s feed disabled"
|
||||
msgid_plural "%s feeds disabled"
|
||||
msgstr[0] "%s flux désactivé"
|
||||
msgstr[1] "%s flux désactivés"
|
||||
|
||||
#: src/BackendBehaviors.php:85
|
||||
msgid "Feeds server: Feeds"
|
||||
msgstr "Serveur de flux : Flux"
|
||||
|
||||
#: src/BackendBehaviors.php:87
|
||||
#: src/FeedsList.php:62
|
||||
#: src/ManageFeed.php:236
|
||||
msgid "Feed"
|
||||
msgstr "Flux"
|
||||
|
||||
#: src/BackendBehaviors.php:95
|
||||
msgid "Feeds server: Entries"
|
||||
msgstr "Serveur de flux : Billets"
|
||||
|
||||
#: src/BackendBehaviors.php:103
|
||||
msgid "Feed server"
|
||||
msgstr "Serveur de flux"
|
||||
|
||||
#: src/BackendBehaviors.php:117
|
||||
msgid "feeds per page"
|
||||
msgstr "flux par page"
|
||||
|
||||
msgid "entries per page"
|
||||
msgstr "billets par page"
|
||||
#: src/BackendBehaviors.php:149
|
||||
msgid "edit feed"
|
||||
msgstr "Modifier le flux"
|
||||
|
||||
#: src/BackendBehaviors.php:225
|
||||
msgid "Edit this feed"
|
||||
msgstr "Modifier ce flux"
|
||||
|
||||
#: src/BackendBehaviors.php:231
|
||||
msgid "Feed source"
|
||||
msgstr "Source du flux"
|
||||
|
||||
#: src/BackendBehaviors.php:238
|
||||
msgid "feed URL"
|
||||
msgstr "URL du fil"
|
||||
|
||||
#: src/BackendBehaviors.php:242
|
||||
msgid "site URL"
|
||||
msgstr "URL du site"
|
||||
|
||||
#: src/Combo.php:35
|
||||
msgid "Update date"
|
||||
msgstr "Date de mise à jour"
|
||||
|
||||
#: src/Combo.php:60
|
||||
msgid "Disabled"
|
||||
msgstr "Désactivé"
|
||||
|
||||
#: src/Combo.php:61
|
||||
msgid "Enabled"
|
||||
msgstr "Activé"
|
||||
|
||||
#: src/Combo.php:82
|
||||
msgid "Every hour"
|
||||
msgstr "Toutes les heures"
|
||||
|
||||
#: src/Combo.php:83
|
||||
msgid "Every two hours"
|
||||
msgstr "Toutes les deux heures"
|
||||
|
||||
#: src/Combo.php:84
|
||||
msgid "Two times per day"
|
||||
msgstr "Deux fois par jour"
|
||||
|
||||
#: src/Combo.php:85
|
||||
msgid "Every day"
|
||||
msgstr "Chaque jour"
|
||||
|
||||
#: src/Combo.php:86
|
||||
msgid "Every two days"
|
||||
msgstr "Tous les deux jours"
|
||||
|
||||
#: src/Combo.php:97
|
||||
msgid "Keep source case"
|
||||
msgstr "Garder la casse de la source"
|
||||
|
||||
#: src/Combo.php:98
|
||||
msgid "First upper case"
|
||||
msgstr "Premier caractère en majuscule"
|
||||
|
||||
#: src/Combo.php:99
|
||||
msgid "All lower case"
|
||||
msgstr "Tout en minuscule"
|
||||
|
||||
#: src/Combo.php:100
|
||||
msgid "All upper case"
|
||||
msgstr "Tout en majuscule"
|
||||
|
||||
#: src/Combo.php:110
|
||||
msgid "Disable"
|
||||
msgstr "Désactiver"
|
||||
|
||||
#: src/Combo.php:111
|
||||
msgid "Before display"
|
||||
msgstr "Avant l'affichage"
|
||||
|
||||
#: src/Combo.php:112
|
||||
msgid "After display"
|
||||
msgstr "Après l'affichage"
|
||||
|
||||
#: src/Combo.php:113
|
||||
msgid "Through Ajax"
|
||||
msgstr "À travers Ajax"
|
||||
|
||||
#: src/Config.php:69
|
||||
msgid "Configuration has been successfully updated."
|
||||
msgstr "La configuration a été mise à jour avec succés."
|
||||
|
||||
#: src/Config.php:101
|
||||
msgid "Dotclear cache is not writable or not well configured!"
|
||||
msgstr "Le cache de Dotclear n'est pas accessible en écriture ou n'est pas configuré !"
|
||||
|
||||
#: src/Config.php:108
|
||||
msgid "View the public list of feeds"
|
||||
msgstr "Voir la page publique de la liste des flux"
|
||||
|
||||
#: src/Config.php:146
|
||||
msgid "Enable plugin"
|
||||
msgstr "Activer le plugin"
|
||||
|
||||
#: src/Config.php:158
|
||||
msgid "Status of new posts:"
|
||||
msgstr "Status des nouveaux billets :"
|
||||
|
||||
#: src/Config.php:166
|
||||
msgid "Owner of entries created by the feed server:"
|
||||
msgstr "Propriétaire des billets créés par le serveur de flux :"
|
||||
|
||||
#: src/Config.php:174
|
||||
msgid "How to transform imported tags:"
|
||||
msgstr "Comment tranformer la casse des mots-clés importés :"
|
||||
|
||||
#: src/Config.php:186
|
||||
msgid "Update feeds on public side:"
|
||||
msgstr "Mettre à jour les flux depuis la partie publique :"
|
||||
|
||||
#: src/Config.php:194
|
||||
msgid "Number of feeds to update at one time:"
|
||||
msgstr "Nombre de flux mis à jour à la fois :"
|
||||
|
||||
#: src/Config.php:205
|
||||
msgid "Keep active empty feeds"
|
||||
msgstr "Garder actif les flux vides"
|
||||
|
||||
#: src/Config.php:213
|
||||
msgid "Enable public page"
|
||||
msgstr "Activer la page publique"
|
||||
|
||||
#: src/Config.php:225
|
||||
msgid "Redirect to original post on:"
|
||||
msgstr "Rediriger vers le billet original sur :"
|
||||
|
||||
#: src/Config.php:232
|
||||
msgid "Show full content on:"
|
||||
msgstr "Afficher le contenu complet sur :"
|
||||
|
||||
#: src/FeedsActions.php:46
|
||||
msgid "Feeds"
|
||||
msgstr "Flux de syndication"
|
||||
|
||||
#: src/FeedsActions.php:61
|
||||
#: src/FeedsDefaultActions.php:271
|
||||
msgid "Feeds server"
|
||||
msgstr "Serveur de flux"
|
||||
|
||||
#: src/FeedsActions.php:67
|
||||
msgid "Back to feeds list"
|
||||
msgstr "Retour à la liste des flux"
|
||||
|
||||
#: src/FeedsActions.php:82
|
||||
msgid "Feeds actions"
|
||||
msgstr "Actions sur les flux"
|
||||
|
||||
#: src/FeedsDefaultActions.php:49
|
||||
msgid "Change update interval"
|
||||
msgstr "Changer l'interval de mise à jour"
|
||||
|
||||
#: src/FeedsDefaultActions.php:53
|
||||
msgid "Disable feed update"
|
||||
msgstr "Désactiver la mise à jour du flux"
|
||||
|
||||
#: src/FeedsDefaultActions.php:57
|
||||
msgid "Enable feed update"
|
||||
msgstr "Activer la mise à jour du flux"
|
||||
|
||||
#: src/FeedsDefaultActions.php:61
|
||||
msgid "Reset last update"
|
||||
msgstr "Remettre à zéro le chronomètre de mise à jour"
|
||||
|
||||
#: src/FeedsDefaultActions.php:65
|
||||
msgid "Update (check) feed"
|
||||
msgstr "Mettre à jour (vérifier) le flux"
|
||||
|
||||
#: src/FeedsDefaultActions.php:69
|
||||
msgid "Delete related posts"
|
||||
msgstr "Effacer les billets liés"
|
||||
|
||||
#: src/FeedsDefaultActions.php:73
|
||||
msgid "Delete feed (without related posts)"
|
||||
msgstr "Effacer le flux (sans effacer les billets liés)"
|
||||
|
||||
#: src/FeedsDefaultActions.php:87
|
||||
msgid "No feeds selected"
|
||||
msgstr "Aucun flux selectionné"
|
||||
|
||||
#: src/FeedsDefaultActions.php:154
|
||||
msgid "Entries have been successfully deleted."
|
||||
msgstr "Les billets ont été effacé avec succès."
|
||||
|
||||
#: src/FeedsDefaultActions.php:205
|
||||
msgid "%d feed has been successfully updated."
|
||||
msgid_plural "%d feeds have been successfully updated."
|
||||
msgstr[0] "%s flux a été mis à jour."
|
||||
msgstr[1] "%s flux ont été mis à jour."
|
||||
|
||||
#: src/FeedsDefaultActions.php:233
|
||||
msgid "Last update of %s feed successfully reseted."
|
||||
msgid_plural "Last update of %s feeds successfully reseted."
|
||||
msgstr[0] "La date de dernière mise à jour de %s flux a été remis à zéro."
|
||||
msgstr[1] "Les date de dernière mise à jour de %s flux ont été remis à zéro."
|
||||
|
||||
#: src/FeedsDefaultActions.php:263
|
||||
msgid "Category of %s feed successfully changed."
|
||||
msgid_plural "Category of %s feeds successfully changed."
|
||||
msgstr[0] "La catégorie de %s flux a été changé."
|
||||
msgstr[1] "Les catégories de %s flux ont été changé."
|
||||
|
||||
#: src/FeedsDefaultActions.php:329
|
||||
msgid "Update frequency of %s feed successfully changed."
|
||||
msgid_plural "Update frequency of %s feeds successfully changed."
|
||||
msgstr[0] "La fréquence de mise à jour de %s flux a été changé."
|
||||
msgstr[1] "Les fréquences de mise à jour de %s flux ont été changé."
|
||||
|
||||
#: src/FeedsDefaultActions.php:340
|
||||
msgid "Change update frequency for this selection"
|
||||
msgstr "Changer la fréquence de mise à jour pour la selection"
|
||||
|
||||
#: src/FeedsDefaultActions.php:355
|
||||
msgid "Frequency:"
|
||||
msgstr "Fréquence :"
|
||||
|
||||
msgid "No entries matches the filter"
|
||||
msgstr "Aucun billet correspondant au filtre."
|
||||
|
||||
msgid "No entries"
|
||||
msgstr "Aucun billet"
|
||||
|
||||
msgid "Feeds"
|
||||
msgstr "Flux de syndication"
|
||||
|
||||
msgid "Back to feeds list"
|
||||
msgstr "Retour à la liste des flux"
|
||||
|
||||
msgid "Feeds actions"
|
||||
msgstr "Actions sur les flux"
|
||||
|
||||
#: src/FeedsList.php:44
|
||||
msgid "No feeds matches the filter"
|
||||
msgstr "Aucun flux correspondant au filtre."
|
||||
|
||||
#: src/FeedsList.php:45
|
||||
msgid "No feeds"
|
||||
msgstr "Aucun flux"
|
||||
|
||||
#: src/FeedsList.php:93
|
||||
msgid "List of %s feeds matching the filter."
|
||||
msgstr "Liste des %s flux correspondant au filtre."
|
||||
|
||||
msgid "List of feeds (%s)"
|
||||
msgstr "Liste des flux (%s)"
|
||||
#: src/FeedsList.php:94
|
||||
msgid "List of feeds. (%s)"
|
||||
msgstr "Liste des flux. (%s)"
|
||||
|
||||
#: src/FeedsList.php:110
|
||||
msgid "enabled"
|
||||
msgstr "activé"
|
||||
|
||||
#: src/FeedsList.php:110
|
||||
msgid "disabled"
|
||||
msgstr "désactivé"
|
||||
|
||||
#: src/FeedsList.php:161
|
||||
msgid "never"
|
||||
msgstr "jamais"
|
||||
|
||||
#: src/FeedsList.php:169
|
||||
msgid "View entries"
|
||||
msgstr "Voir les billets"
|
||||
|
||||
msgid "Original post on <a href=\"%s\">%s</a>"
|
||||
msgstr "Billet original sur <a href=\"%s\">%s</a>"
|
||||
#: src/Manage.php:68
|
||||
msgid "Module is not wel configured"
|
||||
msgstr "Le module n'est pas configuré correctement"
|
||||
|
||||
msgid "Read more details about this feed"
|
||||
msgstr "Lire plus de détails à propos de ce flux"
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr "Désactivé"
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr "Activé"
|
||||
|
||||
msgid "Every hour"
|
||||
msgstr "Toutes les heures"
|
||||
|
||||
msgid "Every two hours"
|
||||
msgstr "Toutes les deux heures"
|
||||
|
||||
msgid "Two times per day"
|
||||
msgstr "Deux fois par jour"
|
||||
|
||||
msgid "Every day"
|
||||
msgstr "Chaque jour"
|
||||
|
||||
msgid "Every two days"
|
||||
msgstr "Tous les deux jours"
|
||||
|
||||
msgid "Entries pages"
|
||||
msgstr "Pages des billets"
|
||||
|
||||
msgid "Tags pages"
|
||||
msgstr "Pages des mots-clés"
|
||||
|
||||
msgid "Archives pages"
|
||||
msgstr "Pages des archives"
|
||||
|
||||
msgid "Category pages"
|
||||
msgstr "Pages de catégories"
|
||||
|
||||
msgid "This feed does not exist."
|
||||
msgstr "Ce flux n'existe pas."
|
||||
|
||||
msgid "next feed"
|
||||
msgstr "flux suivant"
|
||||
|
||||
msgid "previous feed"
|
||||
msgstr "flux précédent"
|
||||
|
||||
msgid "Record with same feed URL already exists."
|
||||
msgstr "Un enregistrement avec la même URL de flux existe déjà."
|
||||
|
||||
msgid "You must provide a name."
|
||||
msgstr "Vous devez indiquer un nom."
|
||||
|
||||
msgid "You must provide an owner."
|
||||
msgstr "Vous devez indiquer un propriétaire."
|
||||
|
||||
msgid "You must provide valid site URL."
|
||||
msgstr "Vous devez donner une URL de site valide."
|
||||
|
||||
msgid "You must provide valid feed URL."
|
||||
msgstr "Vous devez donner une URL de flux valide."
|
||||
|
||||
msgid "You must provide valid category."
|
||||
msgstr "Vous devez donner une catégorie valide."
|
||||
|
||||
msgid "Feed successfully updated."
|
||||
msgstr "Flux mis à jour avec succès."
|
||||
|
||||
msgid "Feed successfully created."
|
||||
msgstr "Flux créé avec succcès."
|
||||
|
||||
msgid "Edit feed"
|
||||
msgstr "Edition de flux"
|
||||
#: src/Manage.php:157
|
||||
msgid "Feeds list"
|
||||
msgstr "Liste de flux"
|
||||
|
||||
#: src/Manage.php:167
|
||||
#: src/ManageFeed.php:212
|
||||
msgid "New feed"
|
||||
msgstr "Nouveau flux"
|
||||
|
||||
#: src/Manage.php:195
|
||||
msgid "Selected feeds action:"
|
||||
msgstr "Action sur les flux sélectionnés :"
|
||||
|
||||
#: src/ManageFeed.php:78
|
||||
msgid "Record with same feed URL already exists."
|
||||
msgstr "Un enregistrement avec la même URL de flux existe déjà."
|
||||
|
||||
#: src/ManageFeed.php:81
|
||||
msgid "You must provide a name."
|
||||
msgstr "Vous devez indiquer un nom."
|
||||
|
||||
#: src/ManageFeed.php:84
|
||||
msgid "You must provide an owner."
|
||||
msgstr "Vous devez indiquer un propriétaire."
|
||||
|
||||
#: src/ManageFeed.php:87
|
||||
msgid "You must provide valid site URL."
|
||||
msgstr "Vous devez donner une URL de site valide."
|
||||
|
||||
#: src/ManageFeed.php:90
|
||||
msgid "You must provide valid feed URL."
|
||||
msgstr "Vous devez donner une URL de flux valide."
|
||||
|
||||
#: src/ManageFeed.php:93
|
||||
msgid "You must provide valid category."
|
||||
msgstr "Vous devez donner une catégorie valide."
|
||||
|
||||
#: src/ManageFeed.php:105
|
||||
msgid "Failed to save feed."
|
||||
msgstr "Impossible de sauvegarder le flux."
|
||||
|
||||
#: src/ManageFeed.php:109
|
||||
msgid "Feed successfully created."
|
||||
msgstr "Flux créé avec succcès."
|
||||
|
||||
#: src/ManageFeed.php:212
|
||||
msgid "Edit feed"
|
||||
msgstr "Edition de flux"
|
||||
|
||||
#: src/ManageFeed.php:215
|
||||
msgid "Edit feed \"%s\""
|
||||
msgstr "Modifier le flux \"%s\""
|
||||
|
||||
#: src/ManageFeed.php:248
|
||||
msgid "Feed information"
|
||||
msgstr "Information sur le flux"
|
||||
|
||||
#: src/ManageFeed.php:264
|
||||
msgid "Owner:"
|
||||
msgstr "Propriétaire :"
|
||||
|
||||
msgid "Tweeter or Identica ident:"
|
||||
msgstr "Identifiant Twiiter ou Identi.ca :"
|
||||
|
||||
#: src/ManageFeed.php:276
|
||||
msgid "Site URL:"
|
||||
msgstr "URL du site :"
|
||||
|
||||
#: src/ManageFeed.php:322
|
||||
msgid "Tweeter or Identica ident:"
|
||||
msgstr "Identifiant Twiiter ou Identi.ca :"
|
||||
|
||||
#: src/ManageFeed.php:334
|
||||
msgid "Local settings"
|
||||
msgstr "Paramètres locaux"
|
||||
|
||||
#: src/ManageFeed.php:358
|
||||
msgid "Update:"
|
||||
msgstr "Mise à jour :"
|
||||
|
||||
#: src/ManageFeed.php:379
|
||||
msgid "Import tags from feed"
|
||||
msgstr "Importer les tags depuis le flux"
|
||||
|
||||
msgid "Selected feeds action:"
|
||||
msgstr "Action sur les flux sélectionnés :"
|
||||
#: src/ManageFeedVars.php:85
|
||||
msgid "This feed does not exist."
|
||||
msgstr "Ce flux n'existe pas."
|
||||
|
||||
#: src/ManageFeedVars.php:115
|
||||
msgid "next feed"
|
||||
msgstr "flux suivant"
|
||||
|
||||
#: src/ManageFeedVars.php:137
|
||||
msgid "previous feed"
|
||||
msgstr "flux précédent"
|
||||
|
||||
#: src/PostsList.php:43
|
||||
msgid "No entries matches the filter"
|
||||
msgstr "Aucun billet correspondant au filtre."
|
||||
|
||||
#: src/PostsList.php:44
|
||||
msgid "No entries"
|
||||
msgstr "Aucun billet"
|
||||
|
||||
#: src/PostsList.php:92
|
||||
msgid "List of entries. (%s)"
|
||||
msgstr "Liste des billets. (%s)"
|
||||
|
||||
#: src/RsExtPosts.php:146
|
||||
msgid "Original post on <a href=\"%s\">%s</a>"
|
||||
msgstr "Billet original sur <a href=\"%s\">%s</a>"
|
||||
|
||||
#: src/RsExtPosts.php:157
|
||||
msgid "Read more details about this feed"
|
||||
msgstr "Lire plus de détails à propos de ce flux"
|
||||
|
||||
#: src/Widgets.php:38
|
||||
msgid "Feeds server: sources"
|
||||
msgstr "Serveur de flux : les sources"
|
||||
|
||||
#: src/Widgets.php:41
|
||||
msgid "List sources of feeds"
|
||||
msgstr "Liste des sources du flux"
|
||||
|
||||
#: src/Widgets.php:44
|
||||
msgid "Feeds sources"
|
||||
msgstr "Sources des flux"
|
||||
|
||||
#: src/Widgets.php:54
|
||||
msgid "Create date"
|
||||
msgstr "Date de création"
|
||||
|
||||
#: src/Widgets.php:69
|
||||
msgid "Limit:"
|
||||
msgstr "Limite :"
|
||||
|
||||
#: src/Widgets.php:75
|
||||
msgid "Link to the list of sources:"
|
||||
msgstr "Lien vers la liste des sources :"
|
||||
|
||||
#: src/Widgets.php:76
|
||||
msgid "All sources"
|
||||
msgstr "Toutes les sources"
|
||||
|
||||
#: src/Widgets.php:87
|
||||
msgid "Feeds server: numbers"
|
||||
msgstr "Serveur de flux : les chiffres"
|
||||
|
||||
#: src/Widgets.php:90
|
||||
msgid "Show some numbers about feeds"
|
||||
msgstr "Afficher quelques chiffres à propose du flux"
|
||||
|
||||
#: src/Widgets.php:93
|
||||
msgid "Feeds numbers"
|
||||
msgstr "Le flux en chiffres"
|
||||
|
||||
#: src/Widgets.php:103
|
||||
msgid "Show feeds count"
|
||||
msgstr "Afficher le nombre de flux"
|
||||
|
||||
#: src/Widgets.php:109
|
||||
msgid "Title for feeds count:"
|
||||
msgstr "Titre pour le nombre de flux :"
|
||||
|
||||
#: src/Widgets.php:110
|
||||
msgid "Feeds:"
|
||||
msgstr "Flux :"
|
||||
|
||||
#: src/Widgets.php:115
|
||||
msgid "Show entries count"
|
||||
msgstr "Afficher le nombre de billets"
|
||||
|
||||
#: src/Widgets.php:121
|
||||
msgid "Title for entries count:"
|
||||
msgstr "Titre pour le nombre de billets :"
|
||||
|
||||
#: src/Widgets.php:122
|
||||
msgid "Entries:"
|
||||
msgstr "Billets :"
|
||||
|
||||
#: src/Widgets.php:219
|
||||
msgid "one source"
|
||||
msgstr "une source"
|
||||
|
||||
#: src/Widgets.php:219
|
||||
msgid "no sources"
|
||||
msgstr "aucune source"
|
||||
|
||||
#: src/Widgets.php:250
|
||||
msgid "one entry"
|
||||
msgstr "une publication"
|
||||
|
||||
#: src/Widgets.php:250
|
||||
msgid "no entries"
|
||||
msgstr "aucune publication"
|
||||
|
||||
#: src/ZoneclearFeedServer.php:964
|
||||
msgid "Entries pages"
|
||||
msgstr "Pages des billets"
|
||||
|
||||
#: src/ZoneclearFeedServer.php:965
|
||||
msgid "Tags pages"
|
||||
msgstr "Pages des mots-clés"
|
||||
|
||||
#: src/ZoneclearFeedServer.php:966
|
||||
msgid "Archives pages"
|
||||
msgstr "Pages des archives"
|
||||
|
||||
#: src/ZoneclearFeedServer.php:967
|
||||
msgid "Category pages"
|
||||
msgstr "Pages de catégories"
|
||||
|
||||
msgid "Mix your blog with a feeds planet"
|
||||
msgstr "Mixer votre blog avec un planet"
|
||||
|
|
|
@ -10,138 +10,137 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
class zcfsActivityReportBehaviors
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use Dotclear\Database\Cursor;
|
||||
use Dotclear\Plugin\activityReport\{
|
||||
Action,
|
||||
ActivityReport,
|
||||
Group
|
||||
};
|
||||
|
||||
/**
|
||||
* Add feeds actions to the plugin activity report.
|
||||
*/
|
||||
class ActivityReportActions
|
||||
{
|
||||
public static function init()
|
||||
public static function init(): void
|
||||
{
|
||||
# This file is used with plugin activityReport
|
||||
dcCore::app()->activityReport->addGroup(
|
||||
'zoneclearFeedServer',
|
||||
__('Plugin zoneclearFeedServer')
|
||||
);
|
||||
$group = new Group(My::id(), My::name());
|
||||
|
||||
# from BEHAVIOR zoneclearFeedServerAfterAddFeed in zoneclearFeedServer/inc/class.zoneclear.feed.server.php
|
||||
dcCore::app()->activityReport->addAction(
|
||||
'zoneclearFeedServer',
|
||||
'create',
|
||||
__('feed creation'),
|
||||
$group->add(new Action(
|
||||
'updateFeed',
|
||||
__('Feed properties update'),
|
||||
__('Feed named "%s" point to "%s" has been updated by "%s"'),
|
||||
'zoneclearFeedServerAfterUpdateFeed',
|
||||
function (Cursor $cur, int $id): void {
|
||||
$user = dcCore::app()->auth?->getInfo('user_cn');
|
||||
if (!is_string($user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rs = ZoneclearFeedServer::instance()->getFeeds(['feed_id' => $id]);
|
||||
if ($rs->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
$row = new FeedRow($rs);
|
||||
|
||||
$logs = [
|
||||
$row->name,
|
||||
$row->feed,
|
||||
$user,
|
||||
];
|
||||
|
||||
ActivityReport::instance()->addLog(My::id(), 'updateFeed', $logs);
|
||||
}
|
||||
));
|
||||
|
||||
$group->add(new Action(
|
||||
'addFeed',
|
||||
__('Feed creation'),
|
||||
__('A new feed named "%s" point to "%s" was added by "%s"'),
|
||||
'zoneclearFeedServerAfterAddFeed',
|
||||
function ($cur) {
|
||||
function (Cursor $cur, int $id): void {
|
||||
$user = dcCore::app()->auth?->getInfo('user_cn');
|
||||
if (!is_string($user)) {
|
||||
return;
|
||||
}
|
||||
$logs = [
|
||||
$cur->feed_name,
|
||||
$cur->feed_feed,
|
||||
dcCore::app()->auth->getInfo('user_cn'),
|
||||
$cur->getField('feed_name'),
|
||||
$cur->getField('feed_feed'),
|
||||
$user,
|
||||
];
|
||||
|
||||
dcCore::app()->activityReport->addLog(
|
||||
'zoneclearFeedServer',
|
||||
'create',
|
||||
$logs
|
||||
);
|
||||
ActivityReport::instance()->addLog(My::id(), 'addFeed', $logs);
|
||||
}
|
||||
);
|
||||
# from BEHAVIOR zoneclearFeedServerAfterUpdFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php
|
||||
dcCore::app()->activityReport->addAction(
|
||||
'zoneclearFeedServer',
|
||||
'updatefeedinfo',
|
||||
__('updating feed info'),
|
||||
__('Feed named "%s" point to "%s" has been updated by "%s"'),
|
||||
'zoneclearFeedServerAfterUpdFeed',
|
||||
function ($cur, $id) {
|
||||
if (defined('DC_CONTEXT_ADMIN')) {
|
||||
$zc = new zoneclearFeedServer();
|
||||
$rs = $zc->getFeeds(['feed_id' => $id]);
|
||||
));
|
||||
|
||||
$logs = [
|
||||
$rs->feed_name,
|
||||
$rs->feed_feed,
|
||||
dcCore::app()->auth->getInfo('user_cn'),
|
||||
];
|
||||
|
||||
dcCore::app()->activityReport->addLog(
|
||||
'zoneclearFeedServer',
|
||||
'updatefeedinfo',
|
||||
$logs
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
# from BEHAVIOR zoneclearFeedServerAfterUpdFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php
|
||||
dcCore::app()->activityReport->addAction(
|
||||
'zoneclearFeedServer',
|
||||
'updatefeedrecords',
|
||||
__('updating feed records'),
|
||||
__('Records of the feed named "%s" have been updated automatically'),
|
||||
'zoneclearFeedServerAfterUpdFeed',
|
||||
function ($cur, $id) {
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
$zc = new zoneclearFeedServer();
|
||||
$rs = $zc->getFeeds(['feed_id' => $id]);
|
||||
|
||||
$logs = [
|
||||
$rs->feed_name,
|
||||
];
|
||||
|
||||
dcCore::app()->activityReport->addLog(
|
||||
'zoneclearFeedServer',
|
||||
'updatefeedrecords',
|
||||
$logs
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
# from BEHAVIOR zoneclearFeedServerAfterDelFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php
|
||||
dcCore::app()->activityReport->addAction(
|
||||
'zoneclearFeedServer',
|
||||
'delete',
|
||||
__('feed deletion'),
|
||||
__('Feed named "%s" point to "%s" has been deleted by "%s"'),
|
||||
'zoneclearFeedServerAfterDelFeed',
|
||||
function ($id) {
|
||||
$zc = new zoneclearFeedServer();
|
||||
$rs = $zc->getFeeds(['feed_id' => $id]);
|
||||
|
||||
$logs = [
|
||||
$rs->feed_name,
|
||||
$rs->feed_feed,
|
||||
dcCore::app()->auth->getInfo('user_cn'),
|
||||
];
|
||||
|
||||
dcCore::app()->activityReport->addLog(
|
||||
'zoneclearFeedServer',
|
||||
'delete',
|
||||
$logs
|
||||
);
|
||||
}
|
||||
);
|
||||
# from BEHAVIOR zoneclearFeedServerAfterEnableFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php
|
||||
dcCore::app()->activityReport->addAction(
|
||||
'zoneclearFeedServer',
|
||||
'status',
|
||||
__('feed status'),
|
||||
$group->add(new Action(
|
||||
'enableFeed',
|
||||
__('Feed status'),
|
||||
__('Feed named "%s" point to "%s" has been set to "%s"'),
|
||||
'zoneclearFeedServerAfterEnableFeed',
|
||||
function ($id, $enable, $time) {
|
||||
$zc = new zoneclearFeedServer();
|
||||
$rs = $zc->getFeeds(['feed_id' => $id]);
|
||||
function (int $id, bool $enable, int $time): void {
|
||||
$rs = ZoneclearFeedServer::instance()->getFeeds(['feed_id' => $id]);
|
||||
if ($rs->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
$row = new FeedRow($rs);
|
||||
|
||||
$logs = [
|
||||
$rs->feed_name,
|
||||
$rs->feed_feed,
|
||||
$enable ? 'enable' : 'disable',
|
||||
$row->name,
|
||||
$row->feed,
|
||||
$enable ? 'enabled' : 'disabled',
|
||||
];
|
||||
|
||||
dcCore::app()->activityReport->addLog(
|
||||
'zoneclearFeedServer',
|
||||
'status',
|
||||
$logs
|
||||
);
|
||||
ActivityReport::instance()->addLog(My::id(), 'enableFeed', $logs);
|
||||
}
|
||||
);
|
||||
));
|
||||
|
||||
$group->add(new Action(
|
||||
'deleteFeed',
|
||||
__('Feed deletion'),
|
||||
__('Feed named "%s" point to "%s" has been deleted by "%s"'),
|
||||
'zoneclearFeedServerBeforeDeleteFeed',
|
||||
function (int $id): void {
|
||||
$rs = ZoneclearFeedServer::instance()->getFeeds(['feed_id' => $id]);
|
||||
if ($rs->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
$row = new FeedRow($rs);
|
||||
|
||||
$user = dcCore::app()->auth?->getInfo('user_cn');
|
||||
if (!is_string($user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$logs = [
|
||||
$row->name,
|
||||
$row->feed,
|
||||
$user,
|
||||
];
|
||||
|
||||
ActivityReport::instance()->addLog(My::id(), 'deleteFeed', $logs);
|
||||
}
|
||||
));
|
||||
|
||||
$group->add(new Action(
|
||||
'checkFeedUpdate',
|
||||
__('Check feed update'),
|
||||
__('Feed named "%s" has been updated automatically'),
|
||||
'zoneclearFeedServerAfterCheckFeedUpdate',
|
||||
function (FeedRow $row): void {
|
||||
$logs = [
|
||||
$row->name,
|
||||
];
|
||||
|
||||
ActivityReport::instance()->addLog(My::id(), 'checkFeedUpdate', $logs);
|
||||
}
|
||||
));
|
||||
|
||||
ActivityReport::instance()->groups->add($group);
|
||||
}
|
||||
}
|
||||
|
|
123
src/Backend.php
123
src/Backend.php
|
@ -10,46 +10,97 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
require_once __DIR__ . '/_widgets.php';
|
||||
use dcAdmin;
|
||||
use dcCore;
|
||||
use dcPage;
|
||||
use dcMenu;
|
||||
use dcNsProcess;
|
||||
|
||||
$perm = dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
|
||||
dcAuth::PERMISSION_CONTENT_ADMIN,
|
||||
]), dcCore::app()->blog->id);
|
||||
/**
|
||||
* Backend prepend.
|
||||
*/
|
||||
class Backend extends dcNsProcess
|
||||
{
|
||||
public static function init(): bool
|
||||
{
|
||||
static::$init = defined('DC_CONTEXT_ADMIN')
|
||||
&& My::phpCompliant();
|
||||
|
||||
if (dcCore::app()->blog->settings->__get(basename(__DIR__))->active
|
||||
&& '' != dcCore::app()->blog->settings->__get(basename(__DIR__))->user
|
||||
) {
|
||||
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
|
||||
__('Feeds server'),
|
||||
dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)),
|
||||
dcPage::getPF(basename(__DIR__) . '/icon.svg'),
|
||||
preg_match(
|
||||
'/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__))) . '(&.*)?$/',
|
||||
$_SERVER['REQUEST_URI']
|
||||
),
|
||||
$perm
|
||||
);
|
||||
|
||||
if ($perm) {
|
||||
# Dashboard icon
|
||||
dcCore::app()->addBehavior('adminDashboardFavoritesV2', ['zcfsAdminBehaviors', 'adminDashboardFavoritesV2']);
|
||||
# User pref
|
||||
dcCore::app()->addBehavior('adminColumnsListsV2', ['zcfsAdminBehaviors', 'adminColumnsListsV2']);
|
||||
dcCore::app()->addBehavior('adminFiltersListsV2', ['zcfsAdminBehaviors', 'adminFiltersListsV2']);
|
||||
# Add info about feed on post page sidebar
|
||||
dcCore::app()->addBehavior('adminPostHeaders', ['zcfsAdminBehaviors', 'adminPostHeaders']);
|
||||
dcCore::app()->addBehavior('adminPostFormItems', ['zcfsAdminBehaviors', 'adminPostFormItems']);
|
||||
return static::$init;
|
||||
}
|
||||
|
||||
# Take care about tweakurls (thanks Mathieu M.)
|
||||
dcCore::app()->addbehavior('zcfsAfterPostCreate', ['zoneclearFeedServer', 'tweakurlsAfterPostCreate']);
|
||||
}
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# Delete related info about feed post in meta table
|
||||
dcCore::app()->addBehavior('adminBeforePostDelete', ['zcfsAdminBehaviors', 'adminBeforePostDelete']);
|
||||
// behaviors that will be always loaded
|
||||
dcCore::app()->addBehaviors([
|
||||
// Allways take care to delete related info about feed post in meta table
|
||||
'adminBeforePostDelete' => function (int $post_id): void {
|
||||
ZoneclearFeedServer::instance()::deletePostsMeta($post_id);
|
||||
},
|
||||
// widgets registration
|
||||
'initWidgets' => [Widgets::class, 'init'],
|
||||
// add Uninstaller cleaner for special direct action
|
||||
'UninstallerCleanersConstruct' => [UninstallCleaner::class, 'init'],
|
||||
]);
|
||||
|
||||
// nullsafe
|
||||
if (is_null(dcCore::app()->auth)
|
||||
|| is_null(dcCore::app()->blog)
|
||||
|| is_null(dcCore::app()->adminurl)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// not active
|
||||
if (!dcCore::app()->blog->settings->get(My::id())->get('active')
|
||||
|| '' == dcCore::app()->blog->settings->get(My::id())->get('user')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get user perm
|
||||
$has_perm = dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
|
||||
dcCore::app()->auth::PERMISSION_CONTENT_ADMIN,
|
||||
]), dcCore::app()->blog->id);
|
||||
|
||||
// add sidebar menu icon
|
||||
if ((dcCore::app()->menu[dcAdmin::MENU_PLUGINS] instanceof dcMenu)) {
|
||||
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
|
||||
My::name(),
|
||||
dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
|
||||
dcPage::getPF(My::id() . '/icon.svg'),
|
||||
preg_match(
|
||||
'/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . My::id())) . '(&.*)?$/',
|
||||
$_SERVER['REQUEST_URI']
|
||||
),
|
||||
$has_perm
|
||||
);
|
||||
}
|
||||
|
||||
// no perm
|
||||
if (!$has_perm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// behaviors that require user perm
|
||||
dcCore::app()->addBehaviors([
|
||||
'adminDashboardFavoritesV2' => [BackendBehaviors::class, 'adminDashboardFavoritesV2'],
|
||||
'adminColumnsListsV2' => [BackendBehaviors::class, 'adminColumnsListsV2'],
|
||||
'adminFiltersListsV2' => [BackendBehaviors::class, 'adminFiltersListsV2'],
|
||||
'adminPostListHeaderV2' => [BackendBehaviors::class, 'adminPostListHeaderV2'],
|
||||
'adminPostListValueV2' => [BackendBehaviors::class, 'adminPostListValueV2'],
|
||||
'adminPostHeaders' => [BackendBehaviors::class, 'adminPostHeaders'],
|
||||
'adminPostFormItems' => [BackendBehaviors::class, 'adminPostFormItems'],
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
248
src/BackendBehaviors.php
Normal file
248
src/BackendBehaviors.php
Normal file
|
@ -0,0 +1,248 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use dcCore;
|
||||
use dcPage;
|
||||
use dcFavorites;
|
||||
use Dotclear\Database\MetaRecord;
|
||||
use Dotclear\Helper\Html\Form\{
|
||||
Checkbox,
|
||||
Div,
|
||||
Input,
|
||||
Label,
|
||||
Link,
|
||||
Para,
|
||||
Text
|
||||
};
|
||||
use Dotclear\Helper\Html\Html;
|
||||
|
||||
/**
|
||||
* Backend behaviors.
|
||||
*/
|
||||
class BackendBehaviors
|
||||
{
|
||||
/**
|
||||
* User dashboard favorites icon.
|
||||
*/
|
||||
public static function adminDashboardFavoritesV2(dcFavorites $favs): void
|
||||
{
|
||||
// nullsafe
|
||||
if (is_null(dcCore::app()->auth) || is_null(dcCore::app()->adminurl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$favs->register(My::id(), [
|
||||
'title' => My::name(),
|
||||
'url' => dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
|
||||
'small-icon' => dcPage::getPF(My::id() . '/icon.svg'),
|
||||
'large-icon' => dcPage::getPF(My::id() . '/icon.svg'),
|
||||
'permissions' => dcCore::app()->auth->makePermissions([
|
||||
dcCore::app()->auth::PERMISSION_USAGE,
|
||||
dcCore::app()->auth::PERMISSION_CONTENT_ADMIN,
|
||||
]),
|
||||
// update user dashboard favorites icon with nb of updated feeds
|
||||
'dashboard_cb' => function (ArrayObject $fav): void {
|
||||
if (is_null(dcCore::app()->adminurl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$count = ZoneclearFeedServer::instance()->getFeeds(['feed_status' => '0'], true)->f(0);
|
||||
if (!$count || !is_numeric($count)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fav['title'] .= '<br />' . sprintf(__('%s feed disabled', '%s feeds disabled', (int) $count), (int) $count);
|
||||
$fav['large-icon'] = dcPage::getPF(My::id() . '/icon-update.svg');
|
||||
$fav['url'] = dcCore::app()->adminurl->get(
|
||||
'admin.plugin.' . My::id(),
|
||||
['part' => 'feeds', 'sortby' => 'feed_status', 'order' => 'asc']
|
||||
);
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists columns user preference.
|
||||
*/
|
||||
public static function adminColumnsListsV2(ArrayObject $cols): void
|
||||
{
|
||||
// feeds
|
||||
$cols[My::id() . 'feeds'] = [
|
||||
__('Feeds server: Feeds'),
|
||||
[
|
||||
'desc' => [true, __('Feed')],
|
||||
'period' => [true, __('Frequency')],
|
||||
'update' => [true, __('Last update')],
|
||||
'entries' => [true, __('Entries')],
|
||||
],
|
||||
];
|
||||
// feed posts
|
||||
$cols[My::id() . 'posts'] = [
|
||||
__('Feeds server: Entries'),
|
||||
[
|
||||
'date' => [true, __('Date')],
|
||||
'category' => [true, __('Category')],
|
||||
'author' => [true, __('Author')],
|
||||
],
|
||||
];
|
||||
// posts feed
|
||||
$cols['posts'][1]['feed'] = [true, __('Feed server')];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists filter.
|
||||
*/
|
||||
public static function adminFiltersListsV2(ArrayObject $sorts): void
|
||||
{
|
||||
// feeds
|
||||
$sorts[My::id() . 'feeds'] = [
|
||||
__('Feeds server: Feeds'),
|
||||
Combo::feedsSortby(),
|
||||
'lowername',
|
||||
'asc',
|
||||
[__('feeds per page'), 30],
|
||||
];
|
||||
// feed posts
|
||||
$sorts[My::id() . 'posts'] = [
|
||||
__('Feeds server: Entries'),
|
||||
Combo::postsSortby(),
|
||||
'post_dt',
|
||||
'desc',
|
||||
[__('entries per page'), 30],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add head column to posts list.
|
||||
*/
|
||||
public static function adminPostListHeaderV2(MetaRecord $rs, ArrayObject $cols): void
|
||||
{
|
||||
$cols['feed'] = '<th scope="col">' . __('Feed') . '</th>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add body column to posts list.
|
||||
*/
|
||||
public static function adminPostListValueV2(MetaRecord $rs, ArrayObject $cols): void
|
||||
{
|
||||
$rs_meta = dcCore::app()->meta->getMetadata(['post_id' => $rs->f('post_id'), 'meta_type' => My::META_PREFIX . 'id']);
|
||||
if ($rs_meta->isEmpty()) {
|
||||
$item = (new Text('', '-'));
|
||||
} else {
|
||||
$row = new FeedRow(ZoneclearFeedServer::instance()->getFeeds(['feed_id' => $rs_meta->f('meta_id')]));
|
||||
$item = (new Link())
|
||||
->href(dcCore::app()->adminurl?->get('admin.plugin.' . My::id(), ['part' => 'feed', 'feed_id' => $row->id]) . '#feed')
|
||||
->title(__('edit feed'))
|
||||
->text(Html::escapeHTML($row->name));
|
||||
}
|
||||
$cols['feed'] = (new Para(null, 'td'))->class('nowrap')->items([$item])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add info about feed on post page sidebar.
|
||||
*/
|
||||
public static function adminPostHeaders(): string
|
||||
{
|
||||
return dcPage::jsModuleLoad(My::id() . '/js/post.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add info about feed on post page sidebar.
|
||||
*/
|
||||
public static function adminPostFormItems(ArrayObject $main_items, ArrayObject $sidebar_items, ?MetaRecord $post): void
|
||||
{
|
||||
// nullsafe
|
||||
if (is_null(dcCore::app()->auth) || is_null(dcCore::app()->blog) || is_null(dcCore::app()->adminurl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// not feed on new post
|
||||
if ($post === null || $post->f('post_type') != 'post') {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = dcCore::app()->meta->getMetadata([
|
||||
'post_id' => $post->f('post_id'),
|
||||
'meta_type' => My::META_PREFIX . 'url',
|
||||
'limit' => 1,
|
||||
]);
|
||||
$url = $url->isEmpty() ? '' : $url->f('meta_id');
|
||||
if (!$url) {
|
||||
return;
|
||||
}
|
||||
|
||||
$author = dcCore::app()->meta->getMetadata([
|
||||
'post_id' => $post->f('post_id'),
|
||||
'meta_type' => My::META_PREFIX . 'author',
|
||||
'limit' => 1,
|
||||
]);
|
||||
$author = $author->isEmpty() ? '' : $author->f('meta_id');
|
||||
|
||||
$site = dcCore::app()->meta->getMetadata([
|
||||
'post_id' => $post->f('post_id'),
|
||||
'meta_type' => My::META_PREFIX . 'site',
|
||||
'limit' => 1,
|
||||
]);
|
||||
$site = $site->isEmpty() ? '' : $site->f('meta_id');
|
||||
|
||||
$sitename = dcCore::app()->meta->getMetadata([
|
||||
'post_id' => $post->f('post_id'),
|
||||
'meta_type' => My::META_PREFIX . 'sitename',
|
||||
'limit' => 1,
|
||||
]);
|
||||
$sitename = $sitename->isEmpty() ? '' : $sitename->f('meta_id');
|
||||
|
||||
$edit = (new Text('', ''));
|
||||
if (dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
|
||||
dcCore::app()->auth::PERMISSION_CONTENT_ADMIN,
|
||||
]), dcCore::app()->blog->id)
|
||||
) {
|
||||
$fid = dcCore::app()->meta->getMetadata([
|
||||
'post_id' => $post->f('post_id'),
|
||||
'meta_type' => My::META_PREFIX . 'id',
|
||||
'limit' => 1,
|
||||
]);
|
||||
if (!$fid->isEmpty()) {
|
||||
$edit = (new Link())
|
||||
->href(dcCore::app()->adminurl->get(
|
||||
'admin.plugin.' . My::id(),
|
||||
['part' => 'feed', 'feed_id' => $fid->f('meta_id')]
|
||||
))
|
||||
->text(__('Edit this feed'));
|
||||
}
|
||||
}
|
||||
|
||||
$sidebar_items['options-box']['items'][My::id()] = (new Div('zcfs'))
|
||||
->items([
|
||||
(new Text('h5', __('Feed source'))),
|
||||
(new Para())
|
||||
->separator('<br />')
|
||||
->items([
|
||||
(new Link())
|
||||
->href($url)
|
||||
->title($author . ' - ' . $url)
|
||||
->text(__('feed URL')),
|
||||
(new Link())
|
||||
->href($site)
|
||||
->title($sitename . ' - ' . $site)
|
||||
->text(__('site URL')),
|
||||
$edit,
|
||||
]),
|
||||
])
|
||||
->render();
|
||||
}
|
||||
}
|
143
src/Combo.php
Normal file
143
src/Combo.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Various combo list.
|
||||
*/
|
||||
class Combo
|
||||
{
|
||||
/**
|
||||
* @return array<string,string>
|
||||
*/
|
||||
public static function feedsSortby(): array
|
||||
{
|
||||
return [
|
||||
__('Date') => 'feed_upddt',
|
||||
__('Name') => 'lowername',
|
||||
__('Frequency') => 'feed_upd_int',
|
||||
__('Update date') => 'feed_upd_last',
|
||||
__('Status') => 'feed_status',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,string>
|
||||
*/
|
||||
public static function postsSortby(): array
|
||||
{
|
||||
return [
|
||||
__('Date') => 'post_dt',
|
||||
__('Title') => 'post_title',
|
||||
__('Category') => 'cat_title',
|
||||
__('Author') => 'user_id',
|
||||
__('Status') => 'post_status',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,string>
|
||||
*/
|
||||
public static function feedsStatus(): array
|
||||
{
|
||||
return [
|
||||
__('Disabled') => '0',
|
||||
__('Enabled') => '1',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,int>
|
||||
*/
|
||||
public static function postsStatus(): array
|
||||
{
|
||||
return [
|
||||
__('Unpublished') => 0,
|
||||
__('Published') => 1,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,int>
|
||||
*/
|
||||
public static function updateInterval(): array
|
||||
{
|
||||
return [
|
||||
__('Every hour') => 3600,
|
||||
__('Every two hours') => 7200,
|
||||
__('Two times per day') => 43200,
|
||||
__('Every day') => 86400,
|
||||
__('Every two days') => 172800,
|
||||
__('Every week') => 604800,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,int>
|
||||
*/
|
||||
public static function tagCase(): array
|
||||
{
|
||||
return [
|
||||
__('Keep source case') => 0,
|
||||
__('First upper case') => 1,
|
||||
__('All lower case') => 2,
|
||||
__('All upper case') => 3,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,int>
|
||||
*/
|
||||
public static function pubUpdate(): array
|
||||
{
|
||||
return [
|
||||
__('Disable') => 0,
|
||||
__('Before display') => 1,
|
||||
__('After display') => 2,
|
||||
__('Through Ajax') => 3,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,string>
|
||||
*/
|
||||
public static function postCategories(): array
|
||||
{
|
||||
$combo = ['-' => ''];
|
||||
|
||||
try {
|
||||
$categories = dcCore::app()->blog?->getCategories(['post_type' => 'post']);
|
||||
if (!is_null($categories)) {
|
||||
while ($categories->fetch()) {
|
||||
$level = is_numeric($categories->f('level')) ? (int) $categories->f('level') : 1;
|
||||
$cat_title = is_string($categories->f('cat_title')) ? $categories->f('cat_title') : '';
|
||||
$cat_id = is_numeric($categories->f('cat_id')) ? (string) $categories->f('cat_id') : '';
|
||||
|
||||
$combo[
|
||||
str_repeat(' ', $level - 1) .
|
||||
'• ' . Html::escapeHTML($cat_title)
|
||||
] = $cat_id;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return $combo;
|
||||
}
|
||||
}
|
389
src/Config.php
389
src/Config.php
|
@ -10,188 +10,233 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_MODULE')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
$redir = empty($_REQUEST['redir']) ? dcCore::app()->admin->list->getURL() . '#plugins' : $_REQUEST['redir'];
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
# -- Get settings --
|
||||
dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
|
||||
$s = dcCore::app()->blog->settings->__get(basename(__DIR__));
|
||||
use adminModulesList;
|
||||
use dcCore;
|
||||
use dcPage;
|
||||
use dcNsProcess;
|
||||
use Dotclear\Helper\Html\Form\{
|
||||
Checkbox,
|
||||
Div,
|
||||
Input,
|
||||
Label,
|
||||
Link,
|
||||
Number,
|
||||
Para,
|
||||
Select,
|
||||
Text
|
||||
};
|
||||
use Exception;
|
||||
|
||||
$active = (bool) $s->active;
|
||||
$pub_active = (bool) $s->pub_active;
|
||||
$post_status_new = (bool) $s->post_status_new;
|
||||
$bhv_pub_upd = (int) $s->bhv_pub_upd;
|
||||
$update_limit = (int) $s->update_limit;
|
||||
$keep_empty_feed = (bool) $s->keep_empty_feed;
|
||||
$tag_case = (int) $s->tag_case;
|
||||
$post_full_tpl = json_decode($s->post_full_tpl);
|
||||
$post_title_redir = json_decode($s->post_title_redir);
|
||||
$feeduser = (string) $s->user;
|
||||
/**
|
||||
* Backend module configuration.
|
||||
*/
|
||||
class Config extends dcNsProcess
|
||||
{
|
||||
public static function init(): bool
|
||||
{
|
||||
static::$init == defined('DC_CONTEXT_ADMIN')
|
||||
&& dcCore::app()->auth?->isSuperAdmin()
|
||||
&& My::phpCompliant();
|
||||
|
||||
if ($update_limit < 1) {
|
||||
$update_limit = 10;
|
||||
}
|
||||
if (!is_array($post_full_tpl)) {
|
||||
$post_full_tpl = [];
|
||||
}
|
||||
if (!is_array($post_title_redir)) {
|
||||
$post_title_redir = [];
|
||||
}
|
||||
|
||||
$zc = new zoneclearFeedServer();
|
||||
|
||||
# -- Set settings --
|
||||
if (!empty($_POST['save'])) {
|
||||
try {
|
||||
$active = !empty($_POST['active']);
|
||||
$pub_active = !empty($_POST['pub_active']);
|
||||
$post_status_new = !empty($_POST['post_status_new']);
|
||||
$bhv_pub_upd = (int) $_POST['bhv_pub_upd'];
|
||||
$limit = abs((int) $_POST['update_limit']);
|
||||
$keep_empty_feed = !empty($_POST['keep_empty_feed']);
|
||||
$tag_case = (int) $_POST['tag_case'];
|
||||
$post_full_tpl = $_POST['post_full_tpl'];
|
||||
$post_title_redir = $_POST['post_title_redir'];
|
||||
$feeduser = (string) $_POST['feeduser'];
|
||||
|
||||
if ($limit < 1) {
|
||||
$limit = 10;
|
||||
return static::$init;
|
||||
}
|
||||
|
||||
$s->put('active', $active);
|
||||
$s->put('pub_active', $pub_active);
|
||||
$s->put('post_status_new', $post_status_new);
|
||||
$s->put('bhv_pub_upd', $bhv_pub_upd);
|
||||
$s->put('update_limit', $limit);
|
||||
$s->put('keep_empty_feed', $keep_empty_feed);
|
||||
$s->put('tag_case', $tag_case);
|
||||
$s->put('post_full_tpl', json_encode($post_full_tpl));
|
||||
$s->put('post_title_redir', json_encode($post_title_redir));
|
||||
$s->put('user', $feeduser);
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dcCore::app()->blog->triggerBlog();
|
||||
// no action
|
||||
if (empty($_POST['save'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(
|
||||
__('Configuration successfully updated.')
|
||||
);
|
||||
dcCore::app()->adminurl->redirect(
|
||||
'admin.plugins',
|
||||
['module' => basename(__DIR__), 'conf' => 1, 'redir' => dcCore::app()->admin->list->getRedir()]
|
||||
// read settings
|
||||
$s = ZoneclearFeedServer::instance()->settings;
|
||||
|
||||
// write settings
|
||||
try {
|
||||
foreach ($s->dump() as $key => $value) {
|
||||
$s->set($key, $_POST[$key] ?? $value);
|
||||
}
|
||||
|
||||
dcPage::addSuccessNotice(
|
||||
__('Configuration has been successfully updated.')
|
||||
);
|
||||
dcCore::app()->adminurl?->redirect('admin.plugins', [
|
||||
'module' => My::id(),
|
||||
'conf' => '1',
|
||||
'redir' => !(dcCore::app()->admin->__get('list') instanceof adminModulesList) ? '' : dcCore::app()->admin->__get('list')->getRedir(),
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function render(): void
|
||||
{
|
||||
if (!static::$init) {
|
||||
return;
|
||||
}
|
||||
|
||||
// nullsafe
|
||||
if (is_null(dcCore::app()->blog)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
|
||||
$msg = [];
|
||||
if (!is_writable(DC_TPL_CACHE)) {
|
||||
$msg[] = (new Para())
|
||||
->class('error')
|
||||
->text(__('Dotclear cache is not writable or not well configured!'));
|
||||
}
|
||||
if ($s->pub_active) {
|
||||
$msg[] = (new Para())
|
||||
->items([
|
||||
(new Link())
|
||||
->class('onblog_link outgoing')
|
||||
->text(__('View the public list of feeds') . ' <img alt="" src="images/outgoing-link.svg">')
|
||||
->href(dcCore::app()->blog->url . dcCore::app()->url->getBase('zoneclearFeedsPage')),
|
||||
]);
|
||||
}
|
||||
|
||||
$titles = [];
|
||||
foreach ($z->getPublicUrlTypes() as $k => $v) {
|
||||
$titles[] = (new Para(null, 'li'))
|
||||
->items([
|
||||
(new Checkbox(['post_title_redir[]', 'post_title_redir_' . $v], in_array($v, $s->post_title_redir)))
|
||||
->value($v),
|
||||
(new Label(__($k), Label::OUTSIDE_LABEL_AFTER))
|
||||
->class('classic')
|
||||
->for('post_title_redir_' . $v),
|
||||
]);
|
||||
}
|
||||
|
||||
$contents = [];
|
||||
foreach ($z->getPublicUrlTypes() as $k => $v) {
|
||||
$contents[] = (new Para(null, 'li'))
|
||||
->items([
|
||||
(new Checkbox(['post_full_tpl_[]', 'post_full_tpl_' . $v], in_array($v, $s->post_full_tpl)))
|
||||
->value($v),
|
||||
(new Label(__($k), Label::OUTSIDE_LABEL_AFTER))
|
||||
->class('classic')
|
||||
->for('post_full_tpl_' . $v),
|
||||
]);
|
||||
}
|
||||
|
||||
echo
|
||||
(new Div())
|
||||
->items([
|
||||
(new Div())
|
||||
->items($msg),
|
||||
(new Para())
|
||||
->items([
|
||||
(new Checkbox('active', $s->active))
|
||||
->value(1),
|
||||
(new Label(__('Enable plugin'), Label::OUTSIDE_LABEL_AFTER))
|
||||
->class('classic')
|
||||
->for('active'),
|
||||
]),
|
||||
(new Div())
|
||||
->class('clear two-cols')
|
||||
->items([
|
||||
(new Div())
|
||||
->class('fieldset col')
|
||||
->items([
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Status of new posts:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('post_status_new'),
|
||||
(new Select('post_status_new'))
|
||||
->items(Combo::postsStatus())
|
||||
->default((string) $s->post_status_new),
|
||||
]),
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Owner of entries created by the feed server:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('user'),
|
||||
(new Select('user'))
|
||||
->items($z->getAllBlogAdmins())
|
||||
->default($s->user),
|
||||
]),
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('How to transform imported tags:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('tag_case'),
|
||||
(new Select('tag_case'))
|
||||
->items(Combo::tagCase())
|
||||
->default((string) $s->tag_case),
|
||||
]),
|
||||
]),
|
||||
(new Div())
|
||||
->class('fieldset col')
|
||||
->items([
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Update feeds on public side:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('bhv_pub_upd'),
|
||||
(new Select('bhv_pub_upd'))
|
||||
->items(Combo::pubUpdate())
|
||||
->default((string) $s->bhv_pub_upd),
|
||||
]),
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Number of feeds to update at one time:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('update_limit'),
|
||||
(new Number('update_limit'))
|
||||
->min(0)
|
||||
->max(20)
|
||||
->value($s->update_limit),
|
||||
]),
|
||||
(new Para())
|
||||
->items([
|
||||
(new Checkbox('keep_empty_feed', $s->keep_empty_feed))
|
||||
->value(1),
|
||||
(new Label(__('Keep active empty feeds'), Label::OUTSIDE_LABEL_AFTER))
|
||||
->class('classic')
|
||||
->for('keep_empty_feed'),
|
||||
]),
|
||||
(new Para())
|
||||
->items([
|
||||
(new Checkbox('pub_active', $s->pub_active))
|
||||
->value(1),
|
||||
(new Label(__('Enable public page'), Label::OUTSIDE_LABEL_AFTER))
|
||||
->class('classic')
|
||||
->for('pub_active'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
(new Div())
|
||||
->class('two-cols')
|
||||
->items([
|
||||
(new Div())
|
||||
->class('fieldset col')
|
||||
->items([
|
||||
(new Text('p', __('Redirect to original post on:'))),
|
||||
(new Para(null, 'ul'))
|
||||
->items($titles),
|
||||
]),
|
||||
(new Div())
|
||||
->class('fieldset col')
|
||||
->items([
|
||||
(new Text('p', __('Show full content on:'))),
|
||||
(new Para(null, 'ul'))
|
||||
->items($contents),
|
||||
]),
|
||||
]),
|
||||
])
|
||||
->render();
|
||||
|
||||
dcPage::helpBlock('zoneclearFeedServer');
|
||||
}
|
||||
}
|
||||
|
||||
# -- Form combos --
|
||||
$combo_admins = $zc->getAllBlogAdmins();
|
||||
$combo_pubupd = [
|
||||
__('Disable') => 0,
|
||||
__('Before display') => 1,
|
||||
__('After display') => 2,
|
||||
__('Through Ajax') => 3,
|
||||
];
|
||||
$combo_status = [
|
||||
__('Unpublished') => 0,
|
||||
__('Published') => 1,
|
||||
];
|
||||
$combo_tagcase = [
|
||||
__('Keep source case') => 0,
|
||||
__('First upper case') => 1,
|
||||
__('All lower case') => 2,
|
||||
__('All upper case') => 3,
|
||||
];
|
||||
|
||||
$pub_page_url = dcCore::app()->blog->url . dcCore::app()->url->getBase('zoneclearFeedsPage');
|
||||
|
||||
# -- Display form --
|
||||
|
||||
if (!is_writable(DC_TPL_CACHE)) {
|
||||
echo '<p class="error">' . __('Dotclear cache is not writable or not well configured!') . '</p>';
|
||||
}
|
||||
|
||||
echo '
|
||||
<div class="fieldset">
|
||||
<h4>' . __('Activation') . '</h4>
|
||||
|
||||
<p><label for="active">' .
|
||||
form::checkbox('active', 1, $active) .
|
||||
__('Enable plugin') . '</label></p>
|
||||
</div>
|
||||
|
||||
<div class="fieldset">';
|
||||
|
||||
if ($s->pub_active) {
|
||||
echo sprintf(
|
||||
'<p><a class="onblog_link outgoing" href="%s" title="%s">%s <img alt="" src="images/outgoing-link.svg"></a></p>',
|
||||
$pub_page_url,
|
||||
$pub_page_url,
|
||||
__('View the public list of feeds')
|
||||
);
|
||||
}
|
||||
|
||||
echo '
|
||||
<h4>' . __('Rules') . '</h4>
|
||||
|
||||
<div class="two-boxes">
|
||||
|
||||
<p><label for="post_status_new">' . __('Status of new posts:') . '</label>' .
|
||||
form::combo('post_status_new', $combo_status, $post_status_new) . '</p>
|
||||
|
||||
<p><label for="feeduser">' .
|
||||
__('Owner of entries created by zoneclearFeedServer:') . '</label>' .
|
||||
form::combo('feeduser', $combo_admins, $feeduser) . '</p>
|
||||
|
||||
<p><label for="tag_case">' . __('How to transform imported tags:') . '</label>' .
|
||||
form::combo('tag_case', $combo_tagcase, $tag_case) . '</p>
|
||||
|
||||
</div><div class="two-boxes">
|
||||
|
||||
<p><label for="bhv_pub_upd">' . __('Update feeds on public side:') . '</label>' .
|
||||
form::combo('bhv_pub_upd', $combo_pubupd, $bhv_pub_upd) . '</p>
|
||||
|
||||
<p class="classic"><label for="update_limit" class="ib">' . sprintf(
|
||||
__('Update %s feed(s) at a time.'),
|
||||
form::number('update_limit', ['min' => 0, 'max' => 20, 'default' => $update_limit])
|
||||
) . '</label></p>
|
||||
|
||||
<p><label for="keep_empty_feed">' .
|
||||
form::checkbox('keep_empty_feed', 1, $keep_empty_feed) . __('Keep active empty feeds') . '</label></p>
|
||||
|
||||
<p><label for="pub_active">' .
|
||||
form::checkbox('pub_active', 1, $pub_active) . __('Enable public page') . '</label></p>
|
||||
|
||||
</div><div class="two-boxes">
|
||||
|
||||
<p>' . __('Redirect to original post on:') . '</p><ul>';
|
||||
|
||||
foreach ($zc->getPublicUrlTypes() as $k => $v) {
|
||||
echo sprintf(
|
||||
'<li><label for="post_title_redir_%s">%s%s</label></li>',
|
||||
$v,
|
||||
form::checkbox(['post_title_redir[]', 'post_title_redir_' . $v], $v, in_array($v, $post_title_redir)),
|
||||
__($k)
|
||||
);
|
||||
}
|
||||
echo '
|
||||
</ul>
|
||||
|
||||
</div><div class="two-boxes">
|
||||
|
||||
<p>' . __('Show full content on:') . '</p><ul>';
|
||||
|
||||
foreach ($zc->getPublicUrlTypes() as $k => $v) {
|
||||
echo sprintf(
|
||||
'<li><label for="post_full_tpl_%s">%s%s</label></li>',
|
||||
$v,
|
||||
form::checkbox(['post_full_tpl[]', 'post_full_tpl_' . $v], $v, in_array($v, $post_full_tpl)),
|
||||
__($k)
|
||||
);
|
||||
}
|
||||
|
||||
echo '</ul></div></div>';
|
||||
|
||||
dcPage::helpBlock('zoneclearFeedServer');
|
||||
|
|
72
src/FeedRow.php
Normal file
72
src/FeedRow.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use Dotclear\Database\MetaRecord;
|
||||
|
||||
/**
|
||||
* Feed meta record row type hinting.
|
||||
*/
|
||||
class FeedRow
|
||||
{
|
||||
public readonly int $id;
|
||||
public readonly int $creadt;
|
||||
public readonly int $upddt;
|
||||
public readonly string $type;
|
||||
public readonly ?string $blog_id;
|
||||
public readonly ?int $cat_id;
|
||||
public readonly int $upd_int;
|
||||
public readonly int $upd_last;
|
||||
public readonly int $status;
|
||||
public readonly string $name;
|
||||
public readonly string $desc;
|
||||
public readonly string $url;
|
||||
public readonly string $feed;
|
||||
public readonly string $tags;
|
||||
public readonly bool $get_tags;
|
||||
public readonly string $owner;
|
||||
public readonly string $tweeter;
|
||||
public readonly string $lang;
|
||||
public readonly int $nb_out;
|
||||
public readonly int $nb_in;
|
||||
|
||||
/**
|
||||
* Constructor sets properties.
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly MetaRecord $rs
|
||||
) {
|
||||
$this->id = is_numeric($this->rs->f('feed_id')) ? (int) $this->rs->f('feed_id') : 0;
|
||||
$this->creadt = is_numeric($this->rs->f('feed_creadt')) ? (int) $this->rs->f('feed_creadt') : 0;
|
||||
$this->upddt = is_numeric($this->rs->f('feed_upddt')) ? (int) $this->rs->f('feed_upddt') : 0;
|
||||
$this->type = is_string($this->rs->f('feed_type')) ? $this->rs->f('feed_type') : '';
|
||||
$this->blog_id = is_string($this->rs->f('blog_id')) ? $this->rs->f('blog_id') : null;
|
||||
$this->cat_id = is_numeric($this->rs->f('cat_id')) ? (int) $this->rs->f('cat_id') : null;
|
||||
$this->upd_int = is_numeric($this->rs->f('feed_upd_int')) ? (int) $this->rs->f('feed_upd_int') : 0;
|
||||
$this->upd_last = is_numeric($this->rs->f('feed_upd_last')) ? (int) $this->rs->f('feed_upd_last') : 0;
|
||||
$this->status = is_numeric($this->rs->f('feed_status')) ? (int) $this->rs->f('feed_status') : 0;
|
||||
$this->name = is_string($this->rs->f('feed_name')) ? $this->rs->f('feed_name') : '';
|
||||
$this->desc = is_string($this->rs->f('feed_desc')) ? $this->rs->f('feed_desc') : '';
|
||||
$this->url = is_string($this->rs->f('feed_url')) ? $this->rs->f('feed_url') : '';
|
||||
$this->feed = is_string($this->rs->f('feed_feed')) ? $this->rs->f('feed_feed') : '';
|
||||
$this->tags = is_string($this->rs->f('feed_tags')) ? $this->rs->f('feed_tags') : '';
|
||||
$this->get_tags = !empty($this->rs->f('feed_get_tags'));
|
||||
$this->owner = is_string($this->rs->f('feed_owner')) ? $this->rs->f('feed_owner') : '';
|
||||
$this->tweeter = is_string($this->rs->f('feed_tweeter')) ? $this->rs->f('feed_tweeter') : '';
|
||||
$this->lang = is_string($this->rs->f('feed_lang')) ? $this->rs->f('feed_lang') : '';
|
||||
$this->nb_out = is_numeric($this->rs->f('feed_nb_out')) ? (int) $this->rs->f('feed_nb_out') : 0;
|
||||
$this->nb_in = is_numeric($this->rs->f('feed_nb_in')) ? (int) $this->rs->f('feed_nb_in') : 0;
|
||||
}
|
||||
}
|
|
@ -10,19 +10,35 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
class zcfsFeedsActions extends dcActions
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use dcActions;
|
||||
use dcCore;
|
||||
use dcPage;
|
||||
use Dotclear\Database\MetaRecord;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Backend feeds list actions handler.
|
||||
*/
|
||||
class FeedsActions extends dcActions
|
||||
{
|
||||
public $zcfs;
|
||||
public ZoneclearFeedServer $zcfs;
|
||||
|
||||
public function __construct($uri, $redirect_args = [])
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param array<string,mixed> $redirect_args
|
||||
*/
|
||||
public function __construct(string $uri, array $redirect_args = [])
|
||||
{
|
||||
$this->zcfs = new zoneclearFeedServer();
|
||||
$this->zcfs = ZoneclearFeedServer::instance();
|
||||
|
||||
parent::__construct($uri, $redirect_args);
|
||||
|
||||
$this->redirect_fields = [
|
||||
'sortby', 'order', 'page', 'nb',
|
||||
];
|
||||
|
@ -31,13 +47,15 @@ class zcfsFeedsActions extends dcActions
|
|||
$this->loadDefaults();
|
||||
}
|
||||
|
||||
protected function loadDefaults()
|
||||
protected function loadDefaults(): void
|
||||
{
|
||||
zcfsDefaultFeedsActions::zcfsFeedsActions($this);
|
||||
dcCore::app()->callBehavior('zcfsFeedsActions', $this);
|
||||
FeedsDefaultActions::addDefaultFeedsActions($this);
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAddFeedsActions - FeedsActions
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAddFeedsActions', $this);
|
||||
}
|
||||
|
||||
public function beginPage($breadcrumb = '', $head = '')
|
||||
public function beginPage(string $breadcrumb = '', string $head = ''): void
|
||||
{
|
||||
echo
|
||||
'<html><head><title>' . __('Feeds server') . '</title>' .
|
||||
|
@ -49,17 +67,17 @@ class zcfsFeedsActions extends dcActions
|
|||
__('Back to feeds list') . '</a></p>';
|
||||
}
|
||||
|
||||
public function endPage()
|
||||
public function endPage(): void
|
||||
{
|
||||
echo '</body></html>';
|
||||
}
|
||||
|
||||
public function error(Exception $e)
|
||||
public function error(Exception $e): void
|
||||
{
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
$this->beginPage(
|
||||
dcPage::breadcrumb([
|
||||
html::escapeHTML(dcCore::app()->blog->name) => '',
|
||||
Html::escapeHTML((string) dcCore::app()->blog?->name) => '',
|
||||
$this->getCallerTitle() => $this->getRedirection(true),
|
||||
__('Feeds actions') => '',
|
||||
])
|
||||
|
@ -67,313 +85,21 @@ class zcfsFeedsActions extends dcActions
|
|||
$this->endPage();
|
||||
}
|
||||
|
||||
protected function fetchEntries($from)
|
||||
protected function fetchEntries(ArrayObject $from): void
|
||||
{
|
||||
if (!empty($from['feeds'])) {
|
||||
$params['feed_id'] = $from['feeds'];
|
||||
if (!empty($from['feeds']) && is_array($from['feeds'])) {
|
||||
$params = [
|
||||
'feed_id' => $from['feeds'],
|
||||
];
|
||||
|
||||
$feeds = $this->zcfs->getFeeds($params);
|
||||
$feeds = ZoneclearFeedServer::instance()->getFeeds($params);
|
||||
while ($feeds->fetch()) {
|
||||
$this->entries[$feeds->feed_id] = $feeds->feed_name;
|
||||
$row = new FeedRow($feeds);
|
||||
$this->entries[$row->id] = $row->name;
|
||||
}
|
||||
$this->rs = $feeds;
|
||||
} else {
|
||||
$this->rs = dcCore::app()->con->select(
|
||||
'SELECT blog_id FROM ' . dcCore::app()->prefix . dcBlog::BLOG_TABLE_NAME . ' WHERE false'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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();
|
||||
$this->rs = MetaRecord::newFromArray([]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,68 +10,90 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use dcCore;
|
||||
use dcMeta;
|
||||
use dcPage;
|
||||
use Dotclear\Database\Statement\DeleteStatement;
|
||||
use Dotclear\Helper\Html\Form\{
|
||||
Form,
|
||||
Hidden,
|
||||
Label,
|
||||
Para,
|
||||
Select,
|
||||
Submit,
|
||||
Text
|
||||
};
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Feeds server - Default actions methods
|
||||
* @since 2.6
|
||||
* @see dcDefaultPostsActionsPage for mor info
|
||||
* Backend feeds list default actions.
|
||||
*/
|
||||
class zcfsDefaultFeedsActions
|
||||
class FeedsDefaultActions
|
||||
{
|
||||
public static function zcfsFeedsActions(zcfsFeedsActions $ap)
|
||||
/**
|
||||
* Add feeds list actions.
|
||||
*/
|
||||
public static function addDefaultFeedsActions(FeedsActions $ap): void
|
||||
{
|
||||
$ap->addAction(
|
||||
[__('Change category') => 'changecat'],
|
||||
['zcfsDefaultFeedsActions', 'doChangeCategory']
|
||||
[self::class, 'doChangeCategory']
|
||||
);
|
||||
$ap->addAction(
|
||||
[__('Change update interval') => 'changeint'],
|
||||
['zcfsDefaultFeedsActions', 'doChangeInterval']
|
||||
[self::class, 'doChangeInterval']
|
||||
);
|
||||
$ap->addAction(
|
||||
[__('Disable feed update') => 'disablefeed'],
|
||||
['zcfsDefaultFeedsActions', 'doEnableFeed']
|
||||
[self::class, 'doEnableFeed']
|
||||
);
|
||||
$ap->addAction(
|
||||
[__('Enable feed update') => 'enablefeed'],
|
||||
['zcfsDefaultFeedsActions', 'doEnableFeed']
|
||||
[self::class, 'doEnableFeed']
|
||||
);
|
||||
$ap->addAction(
|
||||
[__('Reset last update') => 'resetupdlast'],
|
||||
['zcfsDefaultFeedsActions', 'doResetUpdate']
|
||||
[self::class, 'doResetUpdate']
|
||||
);
|
||||
$ap->addAction(
|
||||
[__('Update (check) feed') => 'updatefeed'],
|
||||
['zcfsDefaultFeedsActions', 'doUpdateFeed']
|
||||
[self::class, 'doUpdateFeed']
|
||||
);
|
||||
$ap->addAction(
|
||||
[__('Delete related posts') => 'deletepost'],
|
||||
['zcfsDefaultFeedsActions', 'doDeletePost']
|
||||
[self::class, 'doDeletePost']
|
||||
);
|
||||
$ap->addAction(
|
||||
[__('Delete feed (without related posts)') => 'deletefeed'],
|
||||
['zcfsDefaultFeedsActions', 'doDeleteFeed']
|
||||
[self::class, 'doDeleteFeed']
|
||||
);
|
||||
}
|
||||
|
||||
public static function doEnableFeed(zcfsFeedsActions $ap, $post)
|
||||
/**
|
||||
* Enable / disable feeds.
|
||||
*/
|
||||
public static function doEnableFeed(FeedsActions $ap, ArrayObject $post): void
|
||||
{
|
||||
$enable = $ap->getAction() == 'enablefeed';
|
||||
$ids = $ap->getIDs();
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(__('No feeds selected'));
|
||||
$ap->error(new Exception(__('No feeds selected')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$ap->zcfs->enableFeed($id, $enable);
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(sprintf(
|
||||
dcPage::addSuccessNotice(sprintf(
|
||||
$enable ?
|
||||
__(
|
||||
'%d feed has been successfully enabled.',
|
||||
|
@ -89,20 +111,25 @@ class zcfsDefaultFeedsActions
|
|||
$ap->redirect(true);
|
||||
}
|
||||
|
||||
public static function doDeletePost(zcfsFeedsActions $ap, $post)
|
||||
/**
|
||||
* Delete feeds posts.
|
||||
*/
|
||||
public static function doDeletePost(FeedsActions $ap, ArrayObject $post): void
|
||||
{
|
||||
$types = [
|
||||
'zoneclearfeed_url',
|
||||
'zoneclearfeed_author',
|
||||
'zoneclearfeed_site',
|
||||
'zoneclearfeed_sitename',
|
||||
'zoneclearfeed_id',
|
||||
My::META_PREFIX . 'url',
|
||||
My::META_PREFIX . 'author',
|
||||
My::META_PREFIX . 'site',
|
||||
My::META_PREFIX . 'sitename',
|
||||
My::META_PREFIX . 'id',
|
||||
];
|
||||
|
||||
$ids = $ap->getIDs();
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(__('No feeds selected'));
|
||||
$ap->error(new Exception(__('No feeds selected')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($ids as $id) {
|
||||
|
@ -111,34 +138,42 @@ class zcfsDefaultFeedsActions
|
|||
]);
|
||||
|
||||
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) . ' '
|
||||
);
|
||||
if (is_numeric($posts->f('post_id'))) {
|
||||
dcCore::app()->blog?->delPost((int) $posts->f('post_id'));
|
||||
$sql = new DeleteStatement();
|
||||
$sql
|
||||
->from(dcCore::app()->prefix . dcMeta::META_TABLE_NAME)
|
||||
->where('post_id = ' . $posts->f('post_id'))
|
||||
->and('meta_type ' . $sql->in($types))
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(
|
||||
dcPage::addSuccessNotice(
|
||||
__('Entries have been successfully deleted.')
|
||||
);
|
||||
$ap->redirect(true);
|
||||
}
|
||||
|
||||
public static function doDeleteFeed(zcfsFeedsActions $ap, $post)
|
||||
/**
|
||||
* Delete feeds.
|
||||
*/
|
||||
public static function doDeleteFeed(FeedsActions $ap, ArrayObject $post): void
|
||||
{
|
||||
$ids = $ap->getIDs();
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(__('No feeds selected'));
|
||||
$ap->error(new Exception(__('No feeds selected')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$ap->zcfs->delFeed($id);
|
||||
$ap->zcfs->deleteFeed($id);
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(sprintf(
|
||||
dcPage::addSuccessNotice(sprintf(
|
||||
__(
|
||||
'%d feed has been successfully deleted.',
|
||||
'%d feeds have been successfully deleted.',
|
||||
|
@ -149,77 +184,90 @@ class zcfsDefaultFeedsActions
|
|||
$ap->redirect(true);
|
||||
}
|
||||
|
||||
public static function doUpdateFeed(zcfsFeedsActions $ap, $post)
|
||||
/**
|
||||
* Update feeds properties.
|
||||
*/
|
||||
public static function doUpdateFeed(FeedsActions $ap, ArrayObject $post): void
|
||||
{
|
||||
$ids = $ap->getIDs();
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(__('No feeds selected'));
|
||||
$ap->error(new Exception(__('No feeds selected')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$ap->zcfs->checkFeedsUpdate($id, true);
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(sprintf(
|
||||
dcPage::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)
|
||||
/**
|
||||
* Reset feeds update timer.
|
||||
*/
|
||||
public static function doResetUpdate(FeedsActions $ap, ArrayObject $post): void
|
||||
{
|
||||
$ids = $ap->getIDs();
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(__('No feeds selected'));
|
||||
$ap->error(new Exception(__('No feeds selected')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$cur = $ap->zcfs->openCursor();
|
||||
$cur->feed_upd_last = 0;
|
||||
$ap->zcfs->updFeed($id, $cur);
|
||||
foreach ($ids as $id) {
|
||||
$cur->clean();
|
||||
$cur->setField('feed_upd_last', 0);
|
||||
$ap->zcfs->updateFeed($id, $cur);
|
||||
$ap->zcfs->checkFeedsUpdate($id, true);
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(sprintf(
|
||||
dcPage::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)
|
||||
/**
|
||||
* Change feeds categories.
|
||||
*/
|
||||
public static function doChangeCategory(FeedsActions $ap, ArrayObject $post): void
|
||||
{
|
||||
if (isset($post['upd_cat_id'])) {
|
||||
$ids = $ap->getIDs();
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(__('No feeds selected'));
|
||||
$ap->error(new Exception(__('No feeds selected')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$cat_id = abs((int) $post['upd_cat_id']);
|
||||
$cat_id = is_numeric($post['upd_cat_id']) ? abs((int) $post['upd_cat_id']) : null;
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$cur = $ap->zcfs->openCursor();
|
||||
$cur->cat_id = $cat_id == 0 ? null : $cat_id;
|
||||
$ap->zcfs->updFeed($id, $cur);
|
||||
foreach ($ids as $id) {
|
||||
$cur->clean();
|
||||
$cur->setField('cat_id', $cat_id == 0 ? null : $cat_id);
|
||||
$ap->zcfs->updateFeed($id, $cur);
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(sprintf(
|
||||
dcPage::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) => '',
|
||||
Html::escapeHTML((string) dcCore::app()->blog?->name) => '',
|
||||
__('Feeds server') => '',
|
||||
$ap->getCallerTitle() => $ap->getRedirection(true),
|
||||
__('Change category for this selection') => '',
|
||||
|
@ -227,38 +275,57 @@ class zcfsDefaultFeedsActions
|
|||
);
|
||||
|
||||
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>';
|
||||
(new Form('form-action'))
|
||||
->method('post')
|
||||
->action($ap->getURI())
|
||||
->fields([
|
||||
(new Text('', $ap->getCheckboxes())),
|
||||
(new Para())
|
||||
->items(array_merge(
|
||||
$ap->hiddenFields(),
|
||||
[
|
||||
(new Label(__('Category:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('upd_cat_id'),
|
||||
(new Select('upd_cat_id'))
|
||||
->items(Combo::postCategories()),
|
||||
(new Submit('do-action'))
|
||||
->value(__('Save')),
|
||||
(new Hidden(['action'], 'changecat')),
|
||||
dcCore::app()->formNonce(false),
|
||||
]
|
||||
)),
|
||||
|
||||
])
|
||||
->render();
|
||||
|
||||
$ap->endPage();
|
||||
}
|
||||
}
|
||||
|
||||
public static function doChangeInterval(zcfsFeedsActions $ap, $post)
|
||||
/**
|
||||
* Change feeds update interval.
|
||||
*/
|
||||
public static function doChangeInterval(FeedsActions $ap, ArrayObject $post): void
|
||||
{
|
||||
if (isset($post['upd_upd_int'])) {
|
||||
$ids = $ap->getIDs();
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(__('No feeds selected'));
|
||||
$ap->error(new Exception(__('No feeds selected')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$upd_int = abs((int) $post['upd_upd_int']);
|
||||
$upd_int = is_numeric($post['upd_upd_int']) ? abs((int) $post['upd_upd_int']) : 0;
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$cur = $ap->zcfs->openCursor();
|
||||
$cur->feed_upd_int = $upd_int;
|
||||
$ap->zcfs->updFeed($id, $cur);
|
||||
foreach ($ids as $id) {
|
||||
$cur->clean();
|
||||
$cur->setField('feed_upd_int', $upd_int);
|
||||
$ap->zcfs->updateFeed($id, $cur);
|
||||
}
|
||||
|
||||
dcAdminNotices::addSuccessNotice(sprintf(
|
||||
dcPage::addSuccessNotice(sprintf(
|
||||
__('Update frequency of %s feed successfully changed.', 'Update frequency of %s feeds successfully changed.', count($ids)),
|
||||
count($ids)
|
||||
));
|
||||
|
@ -267,7 +334,7 @@ class zcfsDefaultFeedsActions
|
|||
$ap->beginPage(
|
||||
dcPage::breadcrumb(
|
||||
[
|
||||
html::escapeHTML(dcCore::app()->blog->name) => '',
|
||||
Html::escapeHTML((string) dcCore::app()->blog?->name) => '',
|
||||
__('Feeds server') => '',
|
||||
$ap->getCallerTitle() => $ap->getRedirection(true),
|
||||
__('Change update frequency for this selection') => '',
|
||||
|
@ -276,15 +343,28 @@ class zcfsDefaultFeedsActions
|
|||
);
|
||||
|
||||
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>';
|
||||
(new Form('form-action'))
|
||||
->method('post')
|
||||
->action($ap->getURI())
|
||||
->fields([
|
||||
(new Text('', $ap->getCheckboxes())),
|
||||
(new Para())
|
||||
->items(array_merge(
|
||||
$ap->hiddenFields(),
|
||||
[
|
||||
(new Label(__('Frequency:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('upd_upd_int'),
|
||||
(new Select('upd_upd_int'))
|
||||
->items(Combo::updateInterval()),
|
||||
(new Submit('do-action'))
|
||||
->value(__('Save')),
|
||||
(new Hidden(['action'], 'changeint')),
|
||||
dcCore::app()->formNonce(false),
|
||||
]
|
||||
)),
|
||||
|
||||
])
|
||||
->render();
|
||||
|
||||
$ap->endPage();
|
||||
}
|
||||
|
|
|
@ -10,132 +10,179 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use adminGenericFilterV2;
|
||||
use adminGenericListV2;
|
||||
use dcCore;
|
||||
use dcPager;
|
||||
use Dotclear\Helper\Date;
|
||||
use Dotclear\Helper\Html\Form\{
|
||||
Checkbox,
|
||||
Div,
|
||||
Link,
|
||||
Para,
|
||||
Text
|
||||
};
|
||||
use Dotclear\Helper\Html\Html;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Feeds server - feeds list methods
|
||||
* @since 2.6
|
||||
* @see adminGenericList for more info
|
||||
* Backend feeds list.
|
||||
*/
|
||||
class zcfsFeedsList extends adminGenericList
|
||||
class FeedsList extends adminGenericListV2
|
||||
{
|
||||
private $zc = null;
|
||||
|
||||
public function feedsDisplay($page, $nb_per_page, $enclose_block = '', $filter = false)
|
||||
public function display(adminGenericFilterV2 $filter, string $enclose_block = ''): void
|
||||
{
|
||||
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>';
|
||||
echo
|
||||
(new Text(
|
||||
'p',
|
||||
$filter->show() ?
|
||||
__('No feeds matches the filter') :
|
||||
__('No feeds')
|
||||
))
|
||||
->class('info')
|
||||
->render();
|
||||
|
||||
$cols = [
|
||||
'title' => '<th colspan="2" class="first nowrap">' . __('Name') . '</th>',
|
||||
'desc' => '<th class="nowrap" scope="col">' . __('Feed') . '</th>',
|
||||
'period' => '<th class="nowrap" scope="col">' . __('Frequency') . '</th>',
|
||||
'update' => '<th class="nowrap" scope="col">' . __('Last update') . '</th>',
|
||||
'entries' => '<th class="nowrap" scope="col">' . __('Entries') . '</th>',
|
||||
'status' => '<th class="nowrap" 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);
|
||||
return;
|
||||
}
|
||||
|
||||
echo $pager->getLinks();
|
||||
$page = is_numeric($filter->value('page')) ? (int) $filter->value('page') : 1;
|
||||
$nbpp = is_numeric($filter->value('nb')) ? (int) $filter->value('nb') : 10;
|
||||
$count = (int) $this->rs_count;
|
||||
$pager = new dcPager($page, $count, $nbpp, 10);
|
||||
|
||||
$blocks = explode('%s', $html_block);
|
||||
$cols = new ArrayObject([
|
||||
'title' => (new Text('th', __('Name')))
|
||||
->class('first')
|
||||
->extra('colspan="2"'),
|
||||
'desc' => (new Text('th', __('Feed')))
|
||||
->extra('scope="col"'),
|
||||
'period' => (new Text('th', __('Frequency')))
|
||||
->extra('scope="col"'),
|
||||
'update' => (new Text('th', __('Last update')))
|
||||
->extra('scope="col"')->class('nowrap'),
|
||||
'entries' => (new Text('th', __('Entries')))
|
||||
->extra('scope="col"'),
|
||||
'status' => (new Text('th', __('Status')))
|
||||
->extra('scope="col"'),
|
||||
]);
|
||||
|
||||
echo $blocks[0];
|
||||
$this->userColumns(My::id() . 'feeds', $cols);
|
||||
|
||||
$lines = [];
|
||||
while ($this->rs->fetch()) {
|
||||
echo $this->feedsLine(isset($entries[$this->rs->feed_id]));
|
||||
$lines[] = $this->line(isset($_POST['feeds']) && in_array($this->rs->post_id, $_POST['feeds']));
|
||||
}
|
||||
|
||||
echo $blocks[1];
|
||||
echo $blocks[2];
|
||||
echo $pager->getLinks();
|
||||
}
|
||||
echo
|
||||
$pager->getLinks() .
|
||||
sprintf(
|
||||
$enclose_block,
|
||||
(new Div())
|
||||
->class('table-outer')
|
||||
->items([
|
||||
(new Para(null, 'table'))
|
||||
->items([
|
||||
(new Text(
|
||||
'caption',
|
||||
$filter->show() ?
|
||||
sprintf(__('List of %s feeds matching the filter.'), $this->rs_count) :
|
||||
sprintf(__('List of feeds. (%s)'), $this->rs_count)
|
||||
)),
|
||||
(new Para(null, 'tr'))
|
||||
->items(iterator_to_array($cols)),
|
||||
(new Para(null, 'tbody'))
|
||||
->items($lines),
|
||||
]),
|
||||
])
|
||||
->render()
|
||||
) .
|
||||
$pager->getLinks();
|
||||
}
|
||||
|
||||
private function feedsLine($checked)
|
||||
private function line(bool $checked): Para
|
||||
{
|
||||
$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" />';
|
||||
$row = new FeedRow($this->rs);
|
||||
$img_title = $row->status ? __('enabled') : __('disabled');
|
||||
$img_src = $row->status ? 'check-on.png' : 'check-off.png';
|
||||
|
||||
$entries_count = $this->zc->getPostsByFeed(['feed_id' => $this->rs->feed_id], true)->f(0);
|
||||
$shunk_feed = $this->rs->feed_feed;
|
||||
$entries_count = ZoneclearFeedServer::instance()->getPostsByFeed(['feed_id' => $row->id], true)->f(0);
|
||||
if (!is_numeric($entries_count)) {
|
||||
$entries_count = 0;
|
||||
}
|
||||
|
||||
$shunk_feed = $row->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]);
|
||||
$url = dcCore::app()->adminurl?->get('admin.plugin.' . My::id(), ['part' => 'feed', 'feed_id' => $row->id]);
|
||||
if (!is_string($url)) {
|
||||
$url = '';
|
||||
}
|
||||
$tz = dcCore::app()->auth?->getInfo('user_tz');
|
||||
if (!is_string($tz)) {
|
||||
$tz = 'UTC';
|
||||
}
|
||||
|
||||
$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 ?
|
||||
$cols = new ArrayObject([
|
||||
'check' => (new Para(null, 'td'))
|
||||
->class('nowrap minimal')
|
||||
->items([
|
||||
(new Checkbox(['feeds[]'], $checked))
|
||||
->value($row->id),
|
||||
]),
|
||||
'title' => (new Para(null, 'td'))
|
||||
->class('nowrap')
|
||||
->items([
|
||||
(new Link())
|
||||
->title(__('Edit'))
|
||||
->text(Html::escapeHTML($row->name))
|
||||
->href($url . '#feed'),
|
||||
]),
|
||||
'desc' => (new Para(null, 'td'))
|
||||
->class('nowrap maximal')
|
||||
->items([
|
||||
(new Link())
|
||||
->title(Html::escapeHTML($row->desc))
|
||||
->text(Html::escapeHTML($shunk_feed))
|
||||
->href($row->feed),
|
||||
])
|
||||
->class('nowrap minimal'),
|
||||
'period' => (new Text('td', (string) array_search($row->upd_int, Combo::updateInterval())))
|
||||
->class('nowrap minimal'),
|
||||
'update' => (new Text(
|
||||
'td',
|
||||
$row->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>',
|
||||
];
|
||||
Date::str(__('%Y-%m-%d %H:%M'), $row->upd_last, $tz)
|
||||
))
|
||||
->class('nowrap minimal'),
|
||||
'entries' => (new Para(null, 'td'))
|
||||
->class('nowrap minimal count')
|
||||
->items([
|
||||
(new Link())
|
||||
->title(Html::escapeHTML(__('View entries')))
|
||||
->text(Html::escapeHTML((string) $entries_count))
|
||||
->href($url . '#entries'),
|
||||
]),
|
||||
'status' => (new Para(null, 'td'))
|
||||
->class('nowrap minimal status')
|
||||
->items([
|
||||
(new Text('img', ''))
|
||||
->title($img_title)
|
||||
->extra('src="images/' . $img_src . '"'),
|
||||
]),
|
||||
]);
|
||||
|
||||
$cols = new ArrayObject($cols);
|
||||
dcCore::app()->callBehavior('adminZcfsFeedsListValue', $this->rs, $cols);
|
||||
$this->userColumns(My::id() . 'feeds', $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>';
|
||||
return (new Para('p' . $row->id, 'tr'))
|
||||
->class('line' . ($row->status != 1 ? ' offline ' : ''))
|
||||
->items(iterator_to_array($cols));
|
||||
}
|
||||
}
|
||||
|
|
164
src/Frontend.php
164
src/Frontend.php
|
@ -10,71 +10,109 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
# Namespace for settings
|
||||
dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
|
||||
$s = dcCore::app()->blog->settings->__get(basename(__DIR__));
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
# Widgets
|
||||
require_once __DIR__ . '/_widgets.php';
|
||||
use dcCore;
|
||||
use dcNsProcess;
|
||||
use dcUtils;
|
||||
use Dotclear\Database\MetaRecord;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Exception;
|
||||
|
||||
dcCore::app()->addBehavior('coreBlogGetPosts', ['zcfsPublicBehaviors', 'coreBlogGetPosts']);
|
||||
/**
|
||||
* Frontend prepend.
|
||||
*/
|
||||
class Frontend extends dcNsProcess
|
||||
{
|
||||
public static function init(): bool
|
||||
{
|
||||
static::$init = My::phpCompliant();
|
||||
|
||||
if (!$s->active) {
|
||||
return null;
|
||||
}
|
||||
if (1 == $s->bhv_pub_upd) {
|
||||
dcCore::app()->addBehavior('publicBeforeDocumentV2', ['zcfsPublicBehaviors', 'publicDocumentV2']);
|
||||
} elseif (2 == $s->bhv_pub_upd) {
|
||||
dcCore::app()->addBehavior('publicAfterDocumentV2', ['zcfsPublicBehaviors', 'publicAfterDocumentV2']);
|
||||
} elseif (3 == $s->bhv_pub_upd) {
|
||||
dcCore::app()->addBehavior('publicHeadContent', ['zcfsPublicBehaviors', 'publicHeadContent']);
|
||||
}
|
||||
|
||||
# Take care about tweakurls (thanks Mathieu M.)
|
||||
if (version_compare(dcCore::app()->plugins->moduleInfo('tweakurls', 'version'), '0.8', '>=')) {
|
||||
dcCore::app()->addbehavior('zoneclearFeedServerAfterPostCreate', ['zoneclearFeedServer', 'tweakurlsAfterPostCreate']);
|
||||
}
|
||||
|
||||
# Register tempalte blocks
|
||||
$tpl_blocks = [
|
||||
'Feeds',
|
||||
'FeedsFooter',
|
||||
'FeedsHeader',
|
||||
'FeedIf',
|
||||
];
|
||||
foreach ($tpl_blocks as $v) {
|
||||
dcCore::app()->tpl->addBlock('zc' . $v, ['zcfsTemplate', $v]);
|
||||
}
|
||||
|
||||
# Register tempalte values
|
||||
$tpl_values = [
|
||||
'FeedsCount',
|
||||
'FeedsEntriesCount',
|
||||
'FeedEntriesCount',
|
||||
'FeedCategory',
|
||||
'FeedCategoryID',
|
||||
'FeedCategoryURL',
|
||||
'FeedCategoryShortURL',
|
||||
'FeedID',
|
||||
'FeedIfFirst',
|
||||
'FeedIfOdd',
|
||||
'FeedLang',
|
||||
'FeedName',
|
||||
'FeedOwner',
|
||||
'FeedDesc',
|
||||
'FeedSiteURL',
|
||||
'FeedFeedURL',
|
||||
];
|
||||
foreach ($tpl_values as $v) {
|
||||
dcCore::app()->tpl->addValue('zc' . $v, ['zcfsTemplate', $v]);
|
||||
}
|
||||
|
||||
dcCore::app()->addBehavior('publicBreadcrumb', function ($context, $separator) {
|
||||
if ($context == 'zoneclearFeedsPage') {
|
||||
return __('List of feeds');
|
||||
return static::$init;
|
||||
}
|
||||
});
|
||||
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$s = ZoneclearFeedServer::instance()->settings;
|
||||
|
||||
dcCore::app()->addBehaviors([
|
||||
// posts record
|
||||
'coreBlogGetPosts' => function (MetaRecord $rs): void {
|
||||
RsExtPosts::$brother_extensions = $rs->extensions();
|
||||
$rs->extend(RsExtPosts::class);
|
||||
},
|
||||
// breadcrumb
|
||||
'publicBreadcrumb' => function (string $context, string $separator): string {
|
||||
return $context == 'zoneclearFeedsPage' ? __('List of feeds') : '';
|
||||
},
|
||||
// widgets registration
|
||||
'initWidgets' => [Widgets::class, 'init'],
|
||||
]);
|
||||
|
||||
// Register template blocks
|
||||
foreach (My::TPL_BLOCKS as $block) {
|
||||
dcCore::app()->tpl->addBlock('zc' . $block, [Template::class, $block]);
|
||||
}
|
||||
|
||||
// Register template values
|
||||
foreach (My::TPL_VALUES as $value) {
|
||||
dcCore::app()->tpl->addValue('zc' . $value, [Template::class, $value]);
|
||||
}
|
||||
|
||||
// module not active
|
||||
if (!$s->active) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// feeds update methods
|
||||
if (1 == $s->bhv_pub_upd) {
|
||||
dcCore::app()->addBehavior('publicBeforeDocumentV2', function (): void {
|
||||
if (in_array(dcCore::app()->url->type, ['default', 'feed'])) {
|
||||
try {
|
||||
ZoneclearFeedServer::instance()->checkFeedsUpdate();
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
};
|
||||
});
|
||||
} elseif (2 == $s->bhv_pub_upd) {
|
||||
dcCore::app()->addBehavior('publicAfterDocumentV2', function (): void {
|
||||
try {
|
||||
ZoneclearFeedServer::instance()->checkFeedsUpdate();
|
||||
} catch (Exception $e) {
|
||||
pdump($e);
|
||||
}
|
||||
});
|
||||
} elseif (3 == $s->bhv_pub_upd) {
|
||||
dcCore::app()->addBehavior('publicHeadContent', function (): void {
|
||||
if (is_null(dcCore::app()->blog) || dcCore::app()->url->type != 'default') {
|
||||
return;
|
||||
}
|
||||
|
||||
$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";
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
101
src/Install.php
101
src/Install.php
|
@ -10,56 +10,75 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
try {
|
||||
// Check module version
|
||||
if (!dcCore::app()->newVersion(
|
||||
basename(__DIR__),
|
||||
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version')
|
||||
)) {
|
||||
return null;
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use dcNsProcess;
|
||||
use Dotclear\Database\Structure;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Module installation.
|
||||
*/
|
||||
class Install extends dcNsProcess
|
||||
{
|
||||
public static function init(): bool
|
||||
{
|
||||
if (defined('DC_CONTEXT_ADMIN') && My::phpCompliant()) {
|
||||
$version = dcCore::app()->plugins->moduleInfo(My::id(), 'version');
|
||||
static::$init = is_string($version) ? dcCore::app()->newVersion(My::id(), $version) : true;
|
||||
}
|
||||
|
||||
return static::$init;
|
||||
}
|
||||
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Upgrade existing install
|
||||
zcfsUpgrade::preUpgrade();
|
||||
Upgrade::preUpgrade();
|
||||
|
||||
// Tables
|
||||
$t = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
|
||||
$t->{initZoneclearFeedServer::TABLE_NAME}
|
||||
->feed_id('bigint', 0, false)
|
||||
->feed_creadt('timestamp', 0, false, 'now()')
|
||||
->feed_upddt('timestamp', 0, false, 'now()')
|
||||
->feed_type('varchar', 32, false, "'feed'")
|
||||
->blog_id('varchar', 32, false)
|
||||
->cat_id('bigint', 0, true)
|
||||
->feed_upd_int('integer', 0, false, 3600)
|
||||
->feed_upd_last('integer', 0, false, 0)
|
||||
->feed_status('smallint', 0, false, 0)
|
||||
->feed_name('varchar', 255, false)
|
||||
->feed_desc('text', null, true) //!pgsql reserved 'desc'
|
||||
->feed_url('varchar', 255, false)
|
||||
->feed_feed('varchar', 255, false)
|
||||
->feed_tags('varchar', 255, true)
|
||||
->feed_get_tags('smallint', 0, false, 1)
|
||||
->feed_owner('varchar', 255, false)
|
||||
->feed_tweeter('varchar', 64, false) // tweeter ident
|
||||
->feed_lang('varchar', 5, true)
|
||||
->feed_nb_out('integer', 0, false, 0)
|
||||
->feed_nb_in('integer', 0, false, 0)
|
||||
$s = new Structure(dcCore::app()->con, dcCore::app()->prefix);
|
||||
$s->__get(My::TABLE_NAME)
|
||||
->field('feed_id', 'bigint', 0, false)
|
||||
->field('feed_creadt', 'timestamp', 0, false, 'now()')
|
||||
->field('feed_upddt', 'timestamp', 0, false, 'now()')
|
||||
->field('feed_type', 'varchar', 32, false, "'feed'")
|
||||
->field('blog_id', 'varchar', 32, false)
|
||||
->field('cat_id', 'bigint', 0, true)
|
||||
->field('feed_upd_int', 'integer', 0, false, 3600)
|
||||
->field('feed_upd_last', 'integer', 0, false, 0)
|
||||
->field('feed_status', 'smallint', 0, false, 0)
|
||||
->field('feed_name', 'varchar', 255, false)
|
||||
->field('feed_desc', 'text', null, true) //!pgsql reserved 'desc'
|
||||
->field('feed_url', 'varchar', 255, false)
|
||||
->field('feed_feed', 'varchar', 255, false)
|
||||
->field('feed_tags', 'varchar', 255, true)
|
||||
->field('feed_get_tags', 'smallint', 0, false, 1)
|
||||
->field('feed_owner', 'varchar', 255, false)
|
||||
->field('feed_tweeter', 'varchar', 64, false) // tweeter ident
|
||||
->field('feed_lang', 'varchar', 5, true)
|
||||
->field('feed_nb_out', 'integer', 0, false, 0)
|
||||
->field('feed_nb_in', 'integer', 0, false, 0)
|
||||
|
||||
->primary('pk_zcfs', 'feed_id')
|
||||
->index('idx_zcfs_type', 'btree', 'feed_type')
|
||||
->index('idx_zcfs_blog', 'btree', 'blog_id');
|
||||
|
||||
$ti = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
|
||||
$changes = $ti->synchronize($t);
|
||||
(new Structure(dcCore::app()->con, dcCore::app()->prefix))->synchronize($s);
|
||||
|
||||
// Settings
|
||||
dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
|
||||
$s = dcCore::app()->blog->settings->__get(basename(__DIR__));
|
||||
$s = dcCore::app()->blog?->settings->get(My::id());
|
||||
if (is_null($s)) {
|
||||
return false;
|
||||
}
|
||||
$s->put('active', false, 'boolean', 'Enable zoneclearBlogServer', false, true);
|
||||
$s->put('pub_active', false, 'boolean', 'Enable public page of list of feeds', false, true);
|
||||
$s->put('post_status_new', true, 'boolean', 'Enable auto publish new posts', false, true);
|
||||
|
@ -68,12 +87,14 @@ try {
|
|||
$s->put('keep_empty_feed', false, 'boolean', 'Keep active empty feeds', false, true);
|
||||
$s->put('tag_case', 0, 'integer', 'How to transform imported tags', false, true);
|
||||
$s->put('user', '', 'string', 'User id that has right on post', false, true);
|
||||
$s->put('post_full_tpl', json_encode(['post', 'category', 'tag', 'archive']), 'string', 'List of templates types for full feed', false, true);
|
||||
$s->put('post_title_redir', json_encode(['feed']), 'string', 'List of templates types for redirection to original post', false, true);
|
||||
$s->put('post_full_tpl', ['post', 'category', 'tag', 'archive'], 'array', 'List of templates types for full feed', false, true);
|
||||
$s->put('post_title_redir', ['feed'], 'array', 'List of templates types for redirection to original post', false, true);
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
665
src/Manage.php
665
src/Manage.php
|
@ -10,557 +10,204 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
if (0 !== dcCore::app()->testVersion(
|
||||
basename(__DIR__),
|
||||
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version')
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
dcPage::check(dcCore::app()->auth->makePermissions([
|
||||
dcAuth::PERMISSION_CONTENT_ADMIN,
|
||||
]));
|
||||
use adminGenericFilterV2;
|
||||
use dcAdminFilters;
|
||||
use dcCore;
|
||||
use dcNsProcess;
|
||||
use dcPage;
|
||||
use Dotclear\Helper\Html\Form\{
|
||||
Div,
|
||||
Form,
|
||||
Label,
|
||||
Link,
|
||||
Para,
|
||||
Select,
|
||||
Submit,
|
||||
Text
|
||||
};
|
||||
use Exception;
|
||||
|
||||
$zcfs = new zoneclearFeedServer();
|
||||
/**
|
||||
* Backend feeds list manage page.
|
||||
*/
|
||||
class Manage extends dcNsProcess
|
||||
{
|
||||
public static function init(): bool
|
||||
{
|
||||
static::$init == defined('DC_CONTEXT_ADMIN')
|
||||
&& My::phpCompliant()
|
||||
&& !is_null(dcCore::app()->auth)
|
||||
&& !is_null(dcCore::app()->blog)
|
||||
&& dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
|
||||
dcCore::app()->auth::PERMISSION_CONTENT_ADMIN,
|
||||
]), dcCore::app()->blog->id);
|
||||
|
||||
// call period manage page
|
||||
if (($_REQUEST['part'] ?? 'feeds') === 'feed') {
|
||||
static::$init = ManageFeed::init();
|
||||
}
|
||||
|
||||
return static::$init;
|
||||
}
|
||||
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
|
||||
// not configured
|
||||
if (!$s->active || !$s->user) {
|
||||
dcCore::app()->error->add(__('Module is not wel configured'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// call period manage page
|
||||
if (($_REQUEST['part'] ?? 'feeds') === 'feed') {
|
||||
return ManageFeed::process();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function render(): void
|
||||
{
|
||||
if (!static::$init) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_null(dcCore::app()->adminurl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
|
||||
// not configured
|
||||
if (!$s->active || !$s->user) {
|
||||
dcPage::openModule(My::id());
|
||||
|
||||
# Not configured
|
||||
if (!dcCore::app()->blog->settings->__get(basename(__DIR__))->active
|
||||
|| !dcCore::app()->blog->settings->__get(basename(__DIR__))->user
|
||||
) {
|
||||
echo
|
||||
'<html><head><title>' . __('Feeds server') . '</title></head><body>' .
|
||||
dcPage::breadcrumb([
|
||||
__('Plugins') => '',
|
||||
__('Feeds server') => '',
|
||||
My::name() => '',
|
||||
]) .
|
||||
dcPage::notices();
|
||||
|
||||
############################################################
|
||||
#
|
||||
# One feed
|
||||
#
|
||||
############################################################
|
||||
} elseif (isset($_REQUEST['part']) && $_REQUEST['part'] == 'feed') {
|
||||
$feed_id = '';
|
||||
$feed_name = '';
|
||||
$feed_desc = '';
|
||||
$feed_owner = '';
|
||||
$feed_tweeter = '';
|
||||
$feed_url = '';
|
||||
$feed_feed = '';
|
||||
$feed_lang = dcCore::app()->auth->getInfo('user_lang');
|
||||
$feed_tags = '';
|
||||
$feed_get_tags = '0';
|
||||
$feed_cat_id = '';
|
||||
$feed_status = '0';
|
||||
$feed_upd_int = 3600;
|
||||
dcPage::closeModule();
|
||||
|
||||
$can_view_page = true;
|
||||
|
||||
$feed_headlink = '<link rel="%s" title="%s" href="' . dcCore::app()->admin->getPageURL() . '&part=feed&feed_id=%s" />';
|
||||
$feed_link = '<a href="' . dcCore::app()->admin->getPageURL() . '&part=feed&feed_id=%s" title="%s">%s</a>';
|
||||
|
||||
$next_link = $prev_link = $next_headlink = $prev_headlink = null;
|
||||
|
||||
# Combos
|
||||
$combo_langs = l10n::getISOcodes(true);
|
||||
$combo_status = $zcfs->getAllStatus();
|
||||
$combo_upd_int = $zcfs->getAllUpdateInterval();
|
||||
$combo_categories = ['-' => ''];
|
||||
|
||||
try {
|
||||
$categories = dcCore::app()->blog->getCategories(['post_type' => 'post']);
|
||||
while ($categories->fetch()) {
|
||||
$combo_categories[
|
||||
str_repeat(' ', $categories->level - 1) .
|
||||
'• ' . html::escapeHTML($categories->cat_title)
|
||||
] = $categories->cat_id;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
# Get entry informations
|
||||
if (!empty($_REQUEST['feed_id'])) {
|
||||
$feed = $zcfs->getFeeds(['feed_id' => $_REQUEST['feed_id']]);
|
||||
// call feed manage page
|
||||
if (($_REQUEST['part'] ?? 'feeds') === 'feed') {
|
||||
ManageFeed::render();
|
||||
|
||||
if ($feed->isEmpty()) {
|
||||
dcCore::app()->error->add(__('This feed does not exist.'));
|
||||
$can_view_page = false;
|
||||
} else {
|
||||
$feed_id = $feed->feed_id;
|
||||
$feed_name = $feed->feed_name;
|
||||
$feed_desc = $feed->feed_desc;
|
||||
$feed_owner = $feed->feed_owner;
|
||||
$feed_tweeter = $feed->feed_tweeter;
|
||||
$feed_url = $feed->feed_url;
|
||||
$feed_feed = $feed->feed_feed;
|
||||
$feed_lang = $feed->feed_lang;
|
||||
$feed_tags = $feed->feed_tags;
|
||||
$feed_get_tags = $feed->feed_get_tags;
|
||||
$feed_cat_id = $feed->cat_id;
|
||||
$feed_status = $feed->feed_status;
|
||||
$feed_upd_int = $feed->feed_upd_int;
|
||||
|
||||
$next_params = [
|
||||
'sql' => 'AND feed_id < ' . $feed_id . ' ',
|
||||
'limit' => 1,
|
||||
];
|
||||
$next_rs = $zcfs->getFeeds($next_params);
|
||||
$prev_params = [
|
||||
'sql' => 'AND feed_id > ' . $feed_id . ' ',
|
||||
'limit' => 1,
|
||||
];
|
||||
$prev_rs = $zcfs->getFeeds($prev_params);
|
||||
|
||||
if (!$next_rs->isEmpty()) {
|
||||
$next_link = sprintf(
|
||||
$feed_link,
|
||||
$next_rs->feed_id,
|
||||
html::escapeHTML($next_rs->feed_name),
|
||||
__('next feed') . ' »'
|
||||
);
|
||||
$next_headlink = sprintf(
|
||||
$feed_headlink,
|
||||
'next',
|
||||
html::escapeHTML($next_rs->feed_name),
|
||||
$next_rs->feed_id
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$prev_rs->isEmpty()) {
|
||||
$prev_link = sprintf(
|
||||
$feed_link,
|
||||
$prev_rs->feed_id,
|
||||
html::escapeHTML($prev_rs->feed_name),
|
||||
'« ' . __('previous feed')
|
||||
);
|
||||
$prev_headlink = sprintf(
|
||||
$feed_headlink,
|
||||
'previous',
|
||||
html::escapeHTML($prev_rs->feed_name),
|
||||
$prev_rs->feed_id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_POST['action']) && $_POST['action'] == 'savefeed') {
|
||||
try {
|
||||
$feed_name = $_POST['feed_name'];
|
||||
$feed_desc = $_POST['feed_desc'];
|
||||
$feed_owner = $_POST['feed_owner'];
|
||||
$feed_tweeter = $_POST['feed_tweeter'];
|
||||
$feed_url = $_POST['feed_url'];
|
||||
$feed_feed = $_POST['feed_feed'];
|
||||
$feed_lang = $_POST['feed_lang'];
|
||||
$feed_tags = $_POST['feed_tags'];
|
||||
$feed_get_tags = empty($_POST['feed_get_tags']) ? 0 : 1;
|
||||
$feed_cat_id = $_POST['feed_cat_id'] !== '' ? $_POST['feed_cat_id'] : null;
|
||||
$feed_upd_int = $_POST['feed_upd_int'];
|
||||
if (isset($_POST['feed_status'])) {
|
||||
$feed_status = (int) $_POST['feed_status'];
|
||||
}
|
||||
|
||||
$testfeed_params['feed_feed'] = $feed_feed;
|
||||
if ($feed_id) {
|
||||
$testfeed_params['sql'] = 'AND feed_id <> ' . $feed_id . ' ';
|
||||
}
|
||||
if ($zcfs->getFeeds($testfeed_params, true)->f(0)) {
|
||||
throw new Exception(__('Record with same feed URL already exists.'));
|
||||
}
|
||||
if (empty($feed_name)) {
|
||||
throw new Exception(__('You must provide a name.'));
|
||||
}
|
||||
if (empty($feed_owner)) {
|
||||
throw new Exception(__('You must provide an owner.'));
|
||||
}
|
||||
if (!zoneclearFeedServer::validateURL($feed_url)) {
|
||||
throw new Exception(__('You must provide valid site URL.'));
|
||||
}
|
||||
if (!zoneclearFeedServer::validateURL($feed_feed)) {
|
||||
throw new Exception(__('You must provide valid feed URL.'));
|
||||
}
|
||||
if (null === $feed_cat_id && !dcCore::app()->blog->getCategory((int) $feed_cat_id)) {
|
||||
throw new Exception(__('You must provide valid category.'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_POST['action']) && $_POST['action'] == 'savefeed' && !dcCore::app()->error->flag()) {
|
||||
$cur = $zcfs->openCursor();
|
||||
$cur->feed_name = $feed_name;
|
||||
$cur->feed_desc = $feed_desc;
|
||||
$cur->feed_owner = $feed_owner;
|
||||
$cur->feed_tweeter = $feed_tweeter;
|
||||
$cur->feed_url = $feed_url;
|
||||
$cur->feed_feed = $feed_feed;
|
||||
$cur->feed_lang = $feed_lang;
|
||||
$cur->feed_tags = $feed_tags;
|
||||
$cur->feed_get_tags = (int) $feed_get_tags;
|
||||
$cur->cat_id = null === $feed_cat_id ? null : (int) $feed_cat_id;
|
||||
$cur->feed_status = (int) $feed_status;
|
||||
$cur->feed_upd_int = (int) $feed_upd_int;
|
||||
|
||||
# Update feed
|
||||
if ($feed_id) {
|
||||
try {
|
||||
# --BEHAVIOR-- adminBeforeZoneclearFeedServerFeedUpdate
|
||||
dcCore::app()->callBehavior('adminBeforeZoneclearFeedServerFeedUpdate', $cur, $feed_id);
|
||||
|
||||
$zcfs->updFeed($feed_id, $cur);
|
||||
|
||||
# --BEHAVIOR-- adminAfterZoneclearFeedServerFeedUpdate
|
||||
dcCore::app()->callBehavior('adminAfterZoneclearFeedServerFeedUpdate', $cur, $feed_id);
|
||||
|
||||
dcAdminNotices::addSuccessNotice(
|
||||
__('Feed successfully updated.')
|
||||
);
|
||||
dcCore::app()->adminurl->redirect(
|
||||
'admin.plugin.' . basename(__DIR__),
|
||||
['part' => 'feed', 'feed_id' => $feed_id]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
# --BEHAVIOR-- adminBeforeZoneclearFeedServerFeedCreate
|
||||
dcCore::app()->callBehavior('adminBeforeZoneclearFeedServerFeedCreate', $cur);
|
||||
|
||||
$return_id = $zcfs->addFeed($cur);
|
||||
|
||||
# --BEHAVIOR-- adminAfterZoneclearFeedServerFeedCreate
|
||||
dcCore::app()->callBehavior('adminAfterZoneclearFeedServerFeedCreate', $cur, $return_id);
|
||||
|
||||
dcAdminNotices::addSuccessNotice(
|
||||
__('Feed successfully created.')
|
||||
);
|
||||
dcCore::app()->adminurl->redirect(
|
||||
'admin.plugin.' . basename(__DIR__),
|
||||
['part' => 'feed', 'feed_id' => $return_id]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Prepared entries list
|
||||
if ($feed_id && $can_view_page) {
|
||||
# action
|
||||
$posts_actions_page = new dcPostsActions(
|
||||
// feeds actions
|
||||
$feeds_actions_page = new FeedsActions(
|
||||
'plugin.php',
|
||||
[
|
||||
'p' => basename(__DIR__),
|
||||
'part' => 'feed',
|
||||
'feed_id' => $feed_id,
|
||||
'_ANCHOR' => 'entries',
|
||||
]
|
||||
);
|
||||
if ($posts_actions_page->process()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
# filters
|
||||
$post_filter = new zcfsPostFilter();
|
||||
$post_filter->add('part', 'feed');
|
||||
$post_filter->add('feed_id', $feed_id);
|
||||
$params = $post_filter->params();
|
||||
|
||||
# lexical sort
|
||||
$sortby_lex = [
|
||||
// key in sorty_combo (see above) => field in SQL request
|
||||
'post_title' => 'post_title',
|
||||
'cat_title' => 'cat_title',
|
||||
'user_id' => 'P.user_id', ];
|
||||
|
||||
# --BEHAVIOR-- adminPostsSortbyLexCombo
|
||||
dcCore::app()->callBehavior('adminPostsSortbyLexCombo', [& $sortby_lex]);
|
||||
|
||||
$params['no_content'] = true;
|
||||
$params['feed_id'] = $feed_id;
|
||||
$params['order'] = (array_key_exists($post_filter->sortby, $sortby_lex) ?
|
||||
dcCore::app()->con->lexFields($sortby_lex[$post_filter->sortby]) :
|
||||
$post_filter->sortby) . ' ' . $post_filter->order;
|
||||
|
||||
# posts
|
||||
try {
|
||||
$posts = $zcfs->getPostsByFeed($params);
|
||||
$counter = $zcfs->getPostsByFeed($params, true);
|
||||
$post_list = new zcfsEntriesList(
|
||||
dcCore::app(),
|
||||
$posts,
|
||||
$counter->f(0)
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
# display
|
||||
echo
|
||||
'<html><head><title>' . __('Feeds server') . '</title>' .
|
||||
($feed_id && isset($post_filter) && !dcCore::app()->error->flag() ?
|
||||
$post_filter->js(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'feed', 'feed_id' => $feed_id], '&') . '#entries') .
|
||||
dcPage::jsLoad(dcPage::getPF(basename(__DIR__) . '/js/list.js'))
|
||||
: '') .
|
||||
dcPage::jsPageTabs() .
|
||||
$next_headlink . "\n" . $prev_headlink .
|
||||
|
||||
# --BEHAVIOR-- adminZoneclearFeedServerHeader
|
||||
dcCore::app()->callBehavior('adminZoneclearFeedServerHeader') .
|
||||
|
||||
'</head><body>' .
|
||||
|
||||
dcPage::breadcrumb([
|
||||
__('Plugins') => '',
|
||||
__('Feeds server') => dcCore::app()->admin->getPageURL(),
|
||||
($feed_id ? __('Edit feed') : __('New feed')) => '',
|
||||
]) .
|
||||
dcPage::notices() .
|
||||
($feed_id ? '<h3>' . sprintf(__('Edit feed "%s"'), $feed_name) . '</h3>' : '');
|
||||
|
||||
# Feed
|
||||
if ($can_view_page) {
|
||||
# nav link
|
||||
if ($feed_id && ($next_link || $prev_link)) {
|
||||
echo '<p class="nav_prevnext">';
|
||||
if ($prev_link) {
|
||||
echo $prev_link;
|
||||
}
|
||||
if ($next_link && $prev_link) {
|
||||
echo ' | ';
|
||||
}
|
||||
if ($next_link) {
|
||||
echo $next_link;
|
||||
}
|
||||
echo '</p>';
|
||||
}
|
||||
|
||||
echo '
|
||||
<div' . ($feed_id ? ' class="multi-part" title="' . __('Feed') . '"' : '') . ' id="edit-entry">
|
||||
<form method="post" action="plugin.php">
|
||||
|
||||
<div class="two-cols">' .
|
||||
|
||||
'<div class="col70">' .
|
||||
'<h4>' . __('Feed information') . '</h4>' .
|
||||
|
||||
'<p><label for="feed_name" class="required">
|
||||
<abbr title="' . __('Required field') . '">*</abbr>' .
|
||||
__('Name:') . '</label>' .
|
||||
form::field('feed_name', 60, 255, $feed_name, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_owner" class="required">
|
||||
<abbr title="' . __('Required field') . '">*</abbr>' .
|
||||
__('Owner:') . '</label>' .
|
||||
form::field('feed_owner', 60, 255, $feed_owner, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
// move this away
|
||||
'<p><label for="feed_tweeter">' .
|
||||
__('Tweeter or Identica ident:') . '</label>' .
|
||||
form::field('feed_tweeter', 60, 64, $feed_tweeter, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_url" class="required">
|
||||
<abbr title="' . __('Required field') . '">*</abbr>' .
|
||||
__('Site URL:') . '</label>' .
|
||||
form::field('feed_url', 60, 255, $feed_url, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_feed" class="required">
|
||||
<abbr title="' . __('Required field') . '">*</abbr>' .
|
||||
__('Feed URL:') . '</label>' .
|
||||
form::field('feed_feed', 60, 255, $feed_feed, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_desc">' . __('Description:') . '</label>' .
|
||||
form::field('feed_desc', 60, 255, $feed_desc, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_tags">' . __('Tags:') . '</label>' .
|
||||
form::field('feed_tags', 60, 255, $feed_tags, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
# --BEHAVIOR-- adminZoneclearFeedServerFeedForm
|
||||
dcCore::app()->callBehavior('adminZoneclearFeedServerFeedForm', $feed_id) .
|
||||
|
||||
'</div>' .
|
||||
|
||||
'<div class="col30">' .
|
||||
'<h4>' . __('Local settings') . '</h4>' .
|
||||
|
||||
'<p><label for="feed_cat_id">' . __('Category:') . '</label>' .
|
||||
form::combo('feed_cat_id', $combo_categories, $feed_cat_id, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_status">' . __('Status:') . '</label>' .
|
||||
form::combo('feed_status', $combo_status, $feed_status, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_upd_int">' . __('Update:') . '</label>' .
|
||||
form::combo('feed_upd_int', $combo_upd_int, $feed_upd_int, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_lang">' . __('Lang:') . '</label>' .
|
||||
form::combo('feed_lang', $combo_langs, $feed_lang, 'maximal') .
|
||||
'</p>' .
|
||||
|
||||
'<p><label for="feed_get_tags" class="classic">' .
|
||||
form::checkbox('feed_get_tags', 1, $feed_get_tags) .
|
||||
__('Import tags from feed') . '</label></p>' .
|
||||
|
||||
'</div>' .
|
||||
|
||||
'</div>' .
|
||||
|
||||
'<p class="clear">
|
||||
<input type="submit" name="save" value="' . __('Save') . ' (s)" accesskey="s"/>' .
|
||||
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . basename(__DIR__), [
|
||||
'part' => 'feed',
|
||||
'feed_id' => $feed_id,
|
||||
'action' => 'savefeed',
|
||||
]) .
|
||||
dcCore::app()->formNonce() .
|
||||
'</p>
|
||||
</form>
|
||||
</div>';
|
||||
}
|
||||
|
||||
# entries
|
||||
if ($feed_id && $can_view_page && isset($post_filter) && isset($post_list) && isset($posts_actions_page) && !dcCore::app()->error->flag()) {
|
||||
echo '<div class="multi-part" title="' . __('Entries') . '" id="entries">';
|
||||
|
||||
# show filters
|
||||
$post_filter->display(
|
||||
['admin.plugin.' . basename(__DIR__),'#entries'],
|
||||
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . basename(__DIR__), [
|
||||
'part' => 'feed',
|
||||
'feed_id' => $feed_id,
|
||||
])
|
||||
);
|
||||
|
||||
# fix pager url
|
||||
$args = $post_filter->values();
|
||||
unset($args['page']);
|
||||
$args['page'] = '%s';
|
||||
|
||||
# show posts
|
||||
$post_list->display(
|
||||
$post_filter->page,
|
||||
$post_filter->nb,
|
||||
dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), $args, '&') . '#entries',
|
||||
'<form action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'feed']) . '#entries" method="post" id="form-entries">' .
|
||||
'%s' .
|
||||
|
||||
'<div class="two-cols">' .
|
||||
'<p class="col checkboxes-helpers"></p>' .
|
||||
|
||||
'<p class="col right">' . __('Selected entries action:') . ' ' .
|
||||
form::combo('action', $posts_actions_page->getCombo()) .
|
||||
'<input type="submit" name="save" value="' . __('ok') . '" /></p>' .
|
||||
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . basename(__DIR__), $post_filter->values()) .
|
||||
form::hidden('redir', dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), $post_filter->values())) .
|
||||
dcCore::app()->formNonce() .
|
||||
'</div>' .
|
||||
'</form>',
|
||||
$post_filter->show()
|
||||
);
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
############################################################
|
||||
#
|
||||
# All feeds
|
||||
#
|
||||
############################################################
|
||||
} else {
|
||||
# actions
|
||||
$feeds_actions_page = new zcfsFeedsActions(
|
||||
'plugin.php',
|
||||
['p' => basename(__DIR__), 'part' => 'feeds']
|
||||
['p' => My::id(), 'part' => 'feeds']
|
||||
);
|
||||
if ($feeds_actions_page->process()) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
# filters
|
||||
$feeds_filter = new adminGenericFilter(dcCore::app(), 'zcfs_feeds');
|
||||
// feeds filters
|
||||
$feeds_filter = new adminGenericFilterV2(My::id() . 'feeds');
|
||||
$feeds_filter->add('part', 'feeds');
|
||||
$feeds_filter->add(dcAdminFilters::getPageFilter());
|
||||
$feeds_filter->add(dcAdminFilters::getSearchFilter());
|
||||
$params = $feeds_filter->params();
|
||||
|
||||
# feeds
|
||||
// feeds list
|
||||
try {
|
||||
$feeds = $zcfs->getFeeds($params);
|
||||
$feeds_counter = $zcfs->getFeeds($params, true)->f(0);
|
||||
$feeds_list = new zcfsFeedsList(
|
||||
dcCore::app(),
|
||||
$feeds,
|
||||
$feeds_counter
|
||||
);
|
||||
$feeds = $z->getFeeds($params);
|
||||
$feeds_counter = $z->getFeeds($params, true)->f(0);
|
||||
$feeds_list = new FeedsList($feeds, $feeds_counter);
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
|
||||
# display
|
||||
dcPage::openModule(
|
||||
My::id(),
|
||||
(
|
||||
isset($feeds_list) && !dcCore::app()->error->flag() ?
|
||||
$feeds_filter->js(dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'feeds'], '&')) .
|
||||
dcPage::jsModuleLoad(My::id() . '/js/list.js')
|
||||
: ''
|
||||
) .
|
||||
dcPage::jsPageTabs()
|
||||
);
|
||||
|
||||
echo
|
||||
'<html><head><title>' . __('Feeds server') . '</title>' .
|
||||
$feeds_filter->js(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'feeds'], '&')) .
|
||||
dcPage::jsLoad(dcPage::getPF(basename(__DIR__) . '/js/list.js')) .
|
||||
dcPage::jsPageTabs() .
|
||||
|
||||
# --BEHAVIOR-- adminZoneclearFeedServerHeader
|
||||
dcCore::app()->callBehavior('adminZoneclearFeedServerHeader') .
|
||||
|
||||
'</head><body>' .
|
||||
|
||||
dcPage::breadcrumb([
|
||||
__('Plugins') => '',
|
||||
__('Feeds server') => '',
|
||||
My::name() => dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
|
||||
__('Feeds list') => '',
|
||||
]) .
|
||||
dcPage::notices();
|
||||
|
||||
if (isset($feeds_list)) {
|
||||
echo
|
||||
'<p class="top-add">' .
|
||||
'<a class="button add" href="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'feed']) . '">' .
|
||||
__('New feed') . '</a></p>';
|
||||
(new Para())
|
||||
->class('top-add')
|
||||
->items([
|
||||
(new Link())
|
||||
->class('button add')
|
||||
->text(__('New feed'))
|
||||
->href((string) dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'feed'])),
|
||||
])
|
||||
->render();
|
||||
|
||||
if (isset($feeds_list)) {
|
||||
$feeds_filter->display(
|
||||
'admin.plugin.' . basename(__DIR__),
|
||||
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . basename(__DIR__), ['part' => 'feeds'])
|
||||
'admin.plugin.' . My::id(),
|
||||
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . My::id(), ['part' => 'feeds'])
|
||||
);
|
||||
|
||||
$feeds_list->feedsDisplay(
|
||||
$feeds_filter->page,
|
||||
$feeds_filter->nb,
|
||||
'<form action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'feeds']) . '" method="post" id="form-actions">' .
|
||||
'%s' .
|
||||
'<div class="two-cols">' .
|
||||
'<p class="col checkboxes-helpers"></p>' .
|
||||
'<p class="col right">' . __('Selected feeds action:') . ' ' .
|
||||
form::combo(['action'], $feeds_actions_page->getCombo()) .
|
||||
'<input type="submit" value="' . __('ok') . '" />' .
|
||||
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . basename(__DIR__), $feeds_filter->values(true)) .
|
||||
dcCore::app()->formNonce() .
|
||||
'</p>' .
|
||||
'</div>' .
|
||||
'</form>',
|
||||
$feeds_filter->show()
|
||||
$feeds_list->display(
|
||||
$feeds_filter,
|
||||
(new Form('form-feeds'))
|
||||
->method('post')
|
||||
->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'feeds']))
|
||||
->fields([
|
||||
(new Text('', '%s')),
|
||||
(new Div())
|
||||
->class('two-cols')
|
||||
->items([
|
||||
(new Para())
|
||||
->class('col checkboxes-helpers'),
|
||||
(new Para())
|
||||
->class('col right')
|
||||
->items(array_merge(
|
||||
dcCore::app()->adminurl->hiddenFormFields('admin.plugin.' . My::id(), $feeds_filter->values(true)),
|
||||
[
|
||||
(new Label(__('Selected feeds action:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('action'),
|
||||
(new Select('action'))
|
||||
->items($feeds_actions_page->getCombo()),
|
||||
(new Submit('feeds-action'))
|
||||
->value(__('ok')),
|
||||
dcCore::app()->formNonce(false),
|
||||
|
||||
]
|
||||
)),
|
||||
]),
|
||||
])
|
||||
->render()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
echo '</body></html>';
|
||||
dcPage::closeModule();
|
||||
}
|
||||
}
|
||||
|
|
463
src/ManageFeed.php
Normal file
463
src/ManageFeed.php
Normal file
|
@ -0,0 +1,463 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use dcNsProcess;
|
||||
use dcPage;
|
||||
use dcPostsActions;
|
||||
use Dotclear\Helper\Html\Form\{
|
||||
Checkbox,
|
||||
Div,
|
||||
Form,
|
||||
Hidden,
|
||||
Input,
|
||||
Label,
|
||||
Para,
|
||||
Select,
|
||||
Submit,
|
||||
Text
|
||||
};
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Dotclear\Helper\L10n;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Backend feed and feed posts manage page.
|
||||
*/
|
||||
class ManageFeed extends dcNsProcess
|
||||
{
|
||||
public static function init(): bool
|
||||
{
|
||||
static::$init == defined('DC_CONTEXT_ADMIN')
|
||||
&& My::phpCompliant()
|
||||
&& !is_null(dcCore::app()->auth) && !is_null(dcCore::app()->blog)
|
||||
&& dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
|
||||
dcCore::app()->auth::PERMISSION_CONTENT_ADMIN,
|
||||
]), dcCore::app()->blog->id)
|
||||
&& ($_REQUEST['part'] ?? 'feeds') === 'feed';
|
||||
|
||||
return static::$init;
|
||||
}
|
||||
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// no action
|
||||
if (empty($_POST['action'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
$v = ManageFeedVars::instance();
|
||||
|
||||
// save feed
|
||||
if ($_POST['action'] == 'savefeed') {
|
||||
// check values
|
||||
$testfeed_params['feed_feed'] = $v->feed;
|
||||
if ($v->id) {
|
||||
$testfeed_params['sql'] = 'AND feed_id <> ' . $v->id . ' ';
|
||||
}
|
||||
if ($z->getFeeds($testfeed_params, true)->f(0)) {
|
||||
dcCore::app()->error->add(__('Record with same feed URL already exists.'));
|
||||
}
|
||||
if (empty($v->name)) {
|
||||
dcCore::app()->error->add(__('You must provide a name.'));
|
||||
}
|
||||
if (empty($v->owner)) {
|
||||
dcCore::app()->error->add(__('You must provide an owner.'));
|
||||
}
|
||||
if (!$z::validateURL($v->url)) {
|
||||
dcCore::app()->error->add(__('You must provide valid site URL.'));
|
||||
}
|
||||
if (!$z::validateURL($v->feed)) {
|
||||
dcCore::app()->error->add(__('You must provide valid feed URL.'));
|
||||
}
|
||||
if (null !== $v->cat_id && !dcCore::app()->blog?->getCategory($v->cat_id)) {
|
||||
dcCore::app()->error->add(__('You must provide valid category.'));
|
||||
}
|
||||
|
||||
// check failed
|
||||
if (dcCore::app()->error->flag()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// save feed
|
||||
try {
|
||||
$id = $v->save();
|
||||
if (!$id) {
|
||||
throw new Exception(__('Failed to save feed.'));
|
||||
}
|
||||
|
||||
dcPage::addSuccessNotice(
|
||||
__('Feed successfully created.')
|
||||
);
|
||||
dcCore::app()->adminurl?->redirect(
|
||||
'admin.plugin.' . My::id(),
|
||||
['part' => 'feed', 'feed_id' => $id]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function render(): void
|
||||
{
|
||||
if (!static::$init) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_null(dcCore::app()->adminurl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
$v = ManageFeedVars::instance();
|
||||
|
||||
// Prepared entries list
|
||||
if ($v->id && $v->can_view_page) {
|
||||
// posts actions
|
||||
$posts_actions_page = new dcPostsActions(
|
||||
'plugin.php',
|
||||
[
|
||||
'p' => My::id(),
|
||||
'part' => 'feed',
|
||||
'feed_id' => $v->id,
|
||||
'_ANCHOR' => 'entries',
|
||||
]
|
||||
);
|
||||
if ($posts_actions_page->process()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// posts filters
|
||||
$post_filter = new PostsFilter();
|
||||
$post_filter->add('part', 'feed');
|
||||
$post_filter->add('feed_id', $v->id);
|
||||
$params = $post_filter->params();
|
||||
|
||||
// typehint
|
||||
$sortby = is_string($post_filter->value('sortby')) ? $post_filter->value('sortby') : 'post_creadt';
|
||||
$order = is_string($post_filter->value('order')) ? $post_filter->value('order') : 'DESC';
|
||||
|
||||
# lexical sort
|
||||
$sortby_lex = [
|
||||
// key in sorty_combo (see above) => field in SQL request
|
||||
'post_title' => 'post_title',
|
||||
'cat_title' => 'cat_title',
|
||||
'user_id' => 'P.user_id', ];
|
||||
|
||||
# --BEHAVIOR-- adminPostsSortbyLexCombo
|
||||
dcCore::app()->callBehavior('adminPostsSortbyLexCombo', [& $sortby_lex]);
|
||||
|
||||
$params['no_content'] = true;
|
||||
$params['feed_id'] = $v->id;
|
||||
$params['order'] = (
|
||||
array_key_exists($sortby, $sortby_lex) ?
|
||||
dcCore::app()->con->lexFields($sortby_lex[$sortby]) :
|
||||
$sortby
|
||||
) . ' ' . $order;
|
||||
|
||||
# posts
|
||||
try {
|
||||
$posts = $z->getPostsByFeed($params);
|
||||
$counter = $z->getPostsByFeed($params, true);
|
||||
$post_list = new PostsList($posts, $counter->f(0));
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// display
|
||||
dcPage::openModule(
|
||||
My::id(),
|
||||
(
|
||||
$v->id && isset($post_filter) && !dcCore::app()->error->flag() ?
|
||||
$post_filter->js(dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'feed', 'feed_id' => $v->id], '&') . '#entries') .
|
||||
dcPage::jsModuleLoad(My::id() . '/js/list.js')
|
||||
: ''
|
||||
) .
|
||||
dcPage::jsPageTabs() .
|
||||
$v->next_headlink . "\n" . $v->prev_headlink
|
||||
);
|
||||
|
||||
echo
|
||||
dcPage::breadcrumb([
|
||||
__('Plugins') => '',
|
||||
My::name() => dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
|
||||
($v->id ? __('Edit feed') : __('New feed')) => '',
|
||||
]) .
|
||||
dcPage::notices() .
|
||||
(new Text('h3', ($v->id ? sprintf(__('Edit feed "%s"'), Html::escapeHTML($v->name)) : __('New feed'))))->render();
|
||||
|
||||
if ($v->can_view_page) {
|
||||
# nav link
|
||||
if ($v->id && ($v->next_link || $v->prev_link)) {
|
||||
$text = '';
|
||||
if ($v->prev_link) {
|
||||
$text .= $v->prev_link;
|
||||
}
|
||||
if ($v->next_link && $v->prev_link) {
|
||||
$text .= ' | ';
|
||||
}
|
||||
if ($v->next_link) {
|
||||
$text .= $v->next_link;
|
||||
}
|
||||
echo (new Text('p', $text))->class('nav_prevnext')->render();
|
||||
}
|
||||
|
||||
echo
|
||||
(new Div('edit-entry'))
|
||||
->class($v->id ? 'multi-part' : '')
|
||||
->title($v->id ? __('Feed') : '')
|
||||
->items([
|
||||
(new Form('edit-entry-form'))
|
||||
->method('post')
|
||||
->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id()))
|
||||
->fields([
|
||||
(new Div())
|
||||
->class('two-cols')
|
||||
->items([
|
||||
(new Div())
|
||||
->class('col70')
|
||||
->items([
|
||||
(new Text('h4', __('Feed information'))),
|
||||
// feed_name
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Name:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->class('required')
|
||||
->for('feed_name'),
|
||||
(new Input('feed_name'))
|
||||
->class('maximal')
|
||||
->size(60)
|
||||
->maxlenght(255)
|
||||
->value($v->name),
|
||||
]),
|
||||
// feed_owner
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Owner:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->class('required')
|
||||
->for('feed_owner'),
|
||||
(new Input('feed_owner'))
|
||||
->class('maximal')
|
||||
->size(60)
|
||||
->maxlenght(255)
|
||||
->value($v->owner),
|
||||
]),
|
||||
// feed_url
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Site URL:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->class('required')
|
||||
->for('feed_url'),
|
||||
(new Input('feed_url'))
|
||||
->class('maximal')
|
||||
->size(60)
|
||||
->maxlenght(255)
|
||||
->value($v->url),
|
||||
]),
|
||||
// feed_feed
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Feed URL:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->class('required')
|
||||
->for('feed_feed'),
|
||||
(new Input('feed_feed'))
|
||||
->class('maximal')
|
||||
->size(60)
|
||||
->maxlenght(255)
|
||||
->value($v->feed),
|
||||
]),
|
||||
// feed_desc
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Description:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('feed_desc'),
|
||||
(new Input('feed_desc'))
|
||||
->class('maximal')
|
||||
->size(60)
|
||||
->maxlenght(255)
|
||||
->value($v->desc),
|
||||
]),
|
||||
// feed_tags
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Tags:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('feed_tags'),
|
||||
(new Input('feed_tags'))
|
||||
->class('maximal')
|
||||
->size(60)
|
||||
->maxlenght(255)
|
||||
->value($v->tags),
|
||||
]),
|
||||
// feed_tweeter
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Tweeter or Identica ident:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('feed_tweeter'),
|
||||
(new Input('feed_tweeter'))
|
||||
->class('maximal')
|
||||
->size(60)
|
||||
->maxlenght(255)
|
||||
->value($v->tweeter),
|
||||
]),
|
||||
]),
|
||||
(new Div())
|
||||
->class('col30')
|
||||
->items([
|
||||
(new Text('h4', __('Local settings'))),
|
||||
// feed_cat_id
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Category:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('feed_cat_id'),
|
||||
(new Select('feed_cat_id'))
|
||||
->class('maximal')
|
||||
->items(Combo::postCategories())
|
||||
->default((string) $v->cat_id),
|
||||
]),
|
||||
// feed_status
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Status:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('feed_status'),
|
||||
(new Select('feed_status'))
|
||||
->class('maximal')
|
||||
->items(Combo::feedsStatus())
|
||||
->default((string) $v->status),
|
||||
]),
|
||||
// feed_upd_int
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Update:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('feed_upd_int'),
|
||||
(new Select('feed_upd_int'))
|
||||
->class('maximal')
|
||||
->items(Combo::updateInterval())
|
||||
->default((string) $v->upd_int),
|
||||
]),
|
||||
// feed_lang
|
||||
(new Para())
|
||||
->items([
|
||||
(new Label(__('Lang:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('feed_lang'),
|
||||
(new Select('feed_lang'))
|
||||
->class('maximal')
|
||||
->items(L10n::getISOcodes(true))
|
||||
->default((string) $v->lang),
|
||||
]),
|
||||
// feed_get_tags
|
||||
(new Para())->items([
|
||||
(new Checkbox('feed_get_tags', $v->get_tags))
|
||||
->value(1),
|
||||
(new Label(__('Import tags from feed'), Label::OUTSIDE_LABEL_AFTER))
|
||||
->class('classic')
|
||||
->for('feed_get_tags'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
(new Para())
|
||||
->class('clear')
|
||||
->items(array_merge(
|
||||
dcCore::app()->adminurl->hiddenFormFields('admin.plugin.' . My::id(), [
|
||||
'part' => 'feed',
|
||||
'feed_id' => $v->id,
|
||||
'action' => 'savefeed',
|
||||
]),
|
||||
[
|
||||
(new Submit(['save']))
|
||||
->value(__('Save') . ' (s)')
|
||||
->accesskey('s'),
|
||||
dcCore::app()->formNonce(false),
|
||||
]
|
||||
)),
|
||||
]),
|
||||
])
|
||||
->render();
|
||||
}
|
||||
|
||||
if ($v->id && $v->can_view_page && isset($post_filter) && isset($post_list) && isset($posts_actions_page) && !dcCore::app()->error->flag()) {
|
||||
echo '<div class="multi-part" title="' . __('Entries') . '" id="entries">';
|
||||
|
||||
# show posts filters
|
||||
$post_filter->display(
|
||||
['admin.plugin.' . My::id(),'#entries'],
|
||||
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . My::id(), [
|
||||
'part' => 'feed',
|
||||
'feed_id' => $v->id,
|
||||
])
|
||||
);
|
||||
|
||||
# fix pager url
|
||||
$args = $post_filter->values();
|
||||
unset($args['page']);
|
||||
$args['page'] = '%s';
|
||||
|
||||
# show posts
|
||||
$post_list->display(
|
||||
$post_filter,
|
||||
dcCore::app()->adminurl->get('admin.plugin.' . My::id(), $args, '&') . '#entries',
|
||||
(new Form('form-entries'))
|
||||
->method('post')
|
||||
->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'feed']) . '#entries')
|
||||
->fields([
|
||||
(new Text('', '%s')),
|
||||
(new Div())
|
||||
->class('two-cols')
|
||||
->items([
|
||||
(new Para())
|
||||
->class('col checkboxes-helpers'),
|
||||
(new Para())
|
||||
->class('col right')
|
||||
->items(array_merge(
|
||||
dcCore::app()->adminurl->hiddenFormFields('admin.plugin.' . My::id(), $post_filter->values()),
|
||||
[
|
||||
(new Hidden('redir', dcCore::app()->adminurl->get('admin.plugin.' . My::id(), $post_filter->values()))),
|
||||
(new Label(__('Selected entries action:'), Label::OUTSIDE_LABEL_BEFORE))
|
||||
->for('action'),
|
||||
(new Select('action'))
|
||||
->items($posts_actions_page->getCombo()),
|
||||
(new Submit('feed-action'))
|
||||
->value(__('ok')),
|
||||
dcCore::app()->formNonce(false),
|
||||
|
||||
]
|
||||
)),
|
||||
|
||||
]),
|
||||
])
|
||||
->render()
|
||||
);
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
dcPage::closeModule();
|
||||
}
|
||||
}
|
242
src/ManageFeedVars.php
Normal file
242
src/ManageFeedVars.php
Normal file
|
@ -0,0 +1,242 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
|
||||
/**
|
||||
* Backend feed manage page vars (type hinting).
|
||||
*/
|
||||
class ManageFeedVars
|
||||
{
|
||||
/** @var ManageFeedVars $container Self instance */
|
||||
private static $container;
|
||||
|
||||
public readonly int $id;
|
||||
public readonly string $name;
|
||||
public readonly string $desc;
|
||||
public readonly string $owner;
|
||||
public readonly string $tweeter;
|
||||
public readonly string $url;
|
||||
public readonly string $feed;
|
||||
public readonly string $lang;
|
||||
public readonly string $tags;
|
||||
public readonly bool $get_tags;
|
||||
public readonly ?int $cat_id;
|
||||
public readonly int $status;
|
||||
public readonly int $upd_int;
|
||||
|
||||
public readonly bool $can_view_page;
|
||||
public readonly string $next_link;
|
||||
public readonly string $prev_link;
|
||||
public readonly string $next_headlink;
|
||||
public readonly string $prev_headlink;
|
||||
|
||||
/**
|
||||
* Constructor sets properties.
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
|
||||
$feed_headlink = '<link rel="%s" title="%s" href="' . dcCore::app()->admin->getPageURL() . '&part=feed&feed_id=%s" />';
|
||||
$feed_link = '<a href="' . dcCore::app()->admin->getPageURL() . '&part=feed&feed_id=%s" title="%s">%s</a>';
|
||||
$lang = dcCore::app()->auth?->getInfo('user_lang');
|
||||
|
||||
// default values
|
||||
$feed_id = 0;
|
||||
$feed_name = '';
|
||||
$feed_desc = '';
|
||||
$feed_owner = '';
|
||||
$feed_tweeter = '';
|
||||
$feed_url = '';
|
||||
$feed_feed = '';
|
||||
$feed_lang = is_string($lang) ? $lang : 'en';
|
||||
$feed_tags = '';
|
||||
$feed_get_tags = false;
|
||||
$feed_cat_id = null;
|
||||
$feed_status = 0;
|
||||
$feed_upd_int = 86400;
|
||||
|
||||
$can_view_page = true;
|
||||
$next_link = '';
|
||||
$prev_link = '';
|
||||
$next_headlink = '';
|
||||
$prev_headlink = '';
|
||||
|
||||
// database values
|
||||
if (!empty($_REQUEST['feed_id'])) {
|
||||
$feed = $z->getFeeds(['feed_id' => $_REQUEST['feed_id']]);
|
||||
|
||||
if ($feed->isEmpty()) {
|
||||
dcCore::app()->error->add(__('This feed does not exist.'));
|
||||
$can_view_page = false;
|
||||
} else {
|
||||
$row = new FeedRow($feed);
|
||||
$feed_id = $row->id;
|
||||
$feed_name = $row->name;
|
||||
$feed_desc = $row->desc;
|
||||
$feed_owner = $row->owner;
|
||||
$feed_tweeter = $row->tweeter;
|
||||
$feed_url = $row->url;
|
||||
$feed_feed = $row->feed;
|
||||
$feed_lang = $row->lang;
|
||||
$feed_tags = $row->tags;
|
||||
$feed_get_tags = $row->get_tags;
|
||||
$feed_cat_id = $row->cat_id;
|
||||
$feed_status = $row->status;
|
||||
$feed_upd_int = $row->upd_int;
|
||||
|
||||
$next_params = [
|
||||
'sql' => 'AND feed_id < ' . $feed_id . ' ',
|
||||
'limit' => 1,
|
||||
];
|
||||
$next_rs = $z->getFeeds($next_params);
|
||||
|
||||
if (!$next_rs->isEmpty()) {
|
||||
$next_row = new FeedRow($next_rs);
|
||||
$next_link = sprintf(
|
||||
$feed_link,
|
||||
$next_row->id,
|
||||
Html::escapeHTML($next_row->name),
|
||||
__('next feed') . ' »'
|
||||
);
|
||||
$next_headlink = sprintf(
|
||||
$feed_headlink,
|
||||
'next',
|
||||
Html::escapeHTML($next_row->name),
|
||||
$next_row->id
|
||||
);
|
||||
}
|
||||
|
||||
$prev_params = [
|
||||
'sql' => 'AND feed_id > ' . $feed_id . ' ',
|
||||
'limit' => 1,
|
||||
];
|
||||
$prev_rs = $z->getFeeds($prev_params);
|
||||
|
||||
if (!$prev_rs->isEmpty()) {
|
||||
$prev_row = new FeedRow($prev_rs);
|
||||
$prev_link = sprintf(
|
||||
$feed_link,
|
||||
$prev_row->id,
|
||||
Html::escapeHTML($prev_row->name),
|
||||
'« ' . __('previous feed')
|
||||
);
|
||||
$prev_headlink = sprintf(
|
||||
$feed_headlink,
|
||||
'previous',
|
||||
Html::escapeHTML($prev_row->name),
|
||||
$prev_row->id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// form values
|
||||
if (!empty($_POST)) {
|
||||
$feed_name = !empty($_POST['feed_name']) && is_string($_POST['feed_name']) ? $_POST['feed_name'] : $feed_name;
|
||||
$feed_desc = !empty($_POST['feed_desc']) && is_string($_POST['feed_desc']) ? $_POST['feed_desc'] : $feed_desc;
|
||||
$feed_owner = !empty($_POST['feed_owner']) && is_string($_POST['feed_owner']) ? $_POST['feed_owner'] : $feed_owner;
|
||||
$feed_tweeter = !empty($_POST['feed_tweeter']) && is_string($_POST['feed_tweeter']) ? $_POST['feed_tweeter'] : $feed_tweeter;
|
||||
$feed_url = !empty($_POST['feed_url']) && is_string($_POST['feed_url']) ? $_POST['feed_url'] : $feed_url;
|
||||
$feed_feed = !empty($_POST['feed_feed']) && is_string($_POST['feed_feed']) ? $_POST['feed_feed'] : $feed_feed;
|
||||
$feed_lang = !empty($_POST['feed_lang']) && is_string($_POST['feed_lang']) ? $_POST['feed_lang'] : $feed_lang;
|
||||
$feed_tags = !empty($_POST['feed_tags']) && is_string($_POST['feed_tags']) ? $_POST['feed_tags'] : $feed_tags;
|
||||
$feed_get_tags = empty($_POST['feed_get_tags']) ? $feed_get_tags : true;
|
||||
$feed_cat_id = empty($_POST['feed_cat_id']) ? $feed_cat_id : $_POST['feed_cat_id'];
|
||||
$feed_upd_int = !empty($_POST['feed_upd_int']) && is_numeric($_POST['feed_upd_int']) ? (int) $_POST['feed_upd_int'] : $feed_upd_int;
|
||||
$feed_status = empty($_POST['feed_status']) ? $feed_status : 1;
|
||||
}
|
||||
|
||||
// class values
|
||||
$this->id = $feed_id;
|
||||
$this->name = $feed_name;
|
||||
$this->desc = $feed_desc;
|
||||
$this->owner = $feed_owner;
|
||||
$this->tweeter = $feed_tweeter;
|
||||
$this->url = $feed_url;
|
||||
$this->feed = $feed_feed;
|
||||
$this->lang = $feed_lang;
|
||||
$this->tags = $feed_tags;
|
||||
$this->get_tags = $feed_get_tags;
|
||||
$this->cat_id = $feed_cat_id;
|
||||
$this->status = $feed_status;
|
||||
$this->upd_int = $feed_upd_int;
|
||||
|
||||
$this->can_view_page = $can_view_page;
|
||||
$this->next_link = $next_link;
|
||||
$this->prev_link = $prev_link;
|
||||
$this->next_headlink = $next_headlink;
|
||||
$this->prev_headlink = $prev_headlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get self instance.
|
||||
*
|
||||
* @return ManageFeedVars Self instance
|
||||
*/
|
||||
public static function instance(): ManageFeedVars
|
||||
{
|
||||
if (!(self::$container instanceof self)) {
|
||||
self::$container = new self();
|
||||
}
|
||||
|
||||
return self::$container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update feed.
|
||||
*
|
||||
* @return int The feed ID
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$id = $this->id;
|
||||
|
||||
// prepare cursor
|
||||
$cur = $z->openCursor();
|
||||
$cur->setField('feed_name', $this->name);
|
||||
$cur->setField('feed_desc', $this->desc);
|
||||
$cur->setField('feed_owner', $this->owner);
|
||||
$cur->setField('feed_tweeter', $this->tweeter);
|
||||
$cur->setField('feed_url', $this->url);
|
||||
$cur->setField('feed_feed', $this->feed);
|
||||
$cur->setField('feed_lang', $this->lang);
|
||||
$cur->setField('feed_tags', $this->tags);
|
||||
$cur->setField('feed_get_tags', $this->get_tags);
|
||||
$cur->setField('cat_id', $this->cat_id);
|
||||
$cur->setField('feed_status', $this->status);
|
||||
$cur->setField('feed_upd_int', $this->upd_int);
|
||||
|
||||
# --BEHAVIOR-- adminBeforeZoneclearFeedServerFeedSave - Cursor, int
|
||||
dcCore::app()->callBehavior('adminBeforeZoneclearFeedServerFeedSave', $cur, $id);
|
||||
|
||||
if (!$id) {
|
||||
// create feed
|
||||
$id = $z->addFeed($cur);
|
||||
} else {
|
||||
// update feed
|
||||
$z->updateFeed($id, $cur);
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- adminAfterZoneclearFeedServerFeedSave - Cursor - int
|
||||
dcCore::app()->callBehavior('adminAfterZoneclearFeedServerFeedSave', $cur, $id);
|
||||
|
||||
return $id;
|
||||
}
|
||||
}
|
94
src/My.php
Normal file
94
src/My.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
|
||||
/**
|
||||
* Module definitions.
|
||||
*/
|
||||
class My
|
||||
{
|
||||
/** @var string This module required php version */
|
||||
public const PHP_MIN = '8.1';
|
||||
|
||||
/** @var string This module database table name */
|
||||
public const TABLE_NAME = 'zc_feed';
|
||||
|
||||
/** @var string This module meta prefix */
|
||||
public const META_PREFIX = 'zoneclearfeed_';
|
||||
|
||||
/** @var array<int,string> This module template blocks */
|
||||
public const TPL_BLOCKS = [
|
||||
'Feeds',
|
||||
'FeedsFooter',
|
||||
'FeedsHeader',
|
||||
'FeedIf',
|
||||
];
|
||||
|
||||
/** @var array<int,string> This module template values */
|
||||
public const TPL_VALUES = [
|
||||
'FeedsCount',
|
||||
'FeedsEntriesCount',
|
||||
'FeedEntriesCount',
|
||||
'FeedCategory',
|
||||
'FeedCategoryID',
|
||||
'FeedCategoryURL',
|
||||
'FeedCategoryShortURL',
|
||||
'FeedID',
|
||||
'FeedIfFirst',
|
||||
'FeedIfOdd',
|
||||
'FeedLang',
|
||||
'FeedName',
|
||||
'FeedOwner',
|
||||
'FeedDesc',
|
||||
'FeedSiteURL',
|
||||
'FeedFeedURL',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return string This module id
|
||||
*/
|
||||
public static function id(): string
|
||||
{
|
||||
return basename(dirname(__DIR__));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string This module name
|
||||
*/
|
||||
public static function name(): string
|
||||
{
|
||||
$name = dcCore::app()->plugins->moduleInfo(self::id(), 'name');
|
||||
|
||||
return __(is_string($name) ? $name : self::id());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string This module path
|
||||
*/
|
||||
public static function path(): string
|
||||
{
|
||||
return dirname(__DIR__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool True on this module php version complied
|
||||
*/
|
||||
public static function phpCompliant(): bool
|
||||
{
|
||||
return version_compare(phpversion(), self::PHP_MIN, '>=');
|
||||
}
|
||||
}
|
|
@ -10,23 +10,31 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use adminGenericFilterV2;
|
||||
use dcAdminCombos;
|
||||
use dcAdminFilter;
|
||||
use dcAdminFilters;
|
||||
use dcCore;
|
||||
use dcUtils;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Feeds server - Posts list filters methods
|
||||
* @since 2.20
|
||||
* @see adminGenericFilter for more info
|
||||
* Backend feed posts list filters.
|
||||
*/
|
||||
class zcfsPostFilter extends adminGenericFilter
|
||||
class PostsFilter extends adminGenericFilterV2
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(dcCore::app(), 'zcfs_entries');
|
||||
// use user posts pref
|
||||
parent::__construct('posts');
|
||||
|
||||
$filters = new arrayObject([
|
||||
$filters = new ArrayObject([
|
||||
dcAdminFilters::getPageFilter(),
|
||||
$this->getPostUserFilter(),
|
||||
$this->getPostCategoriesFilter(),
|
||||
|
@ -50,8 +58,8 @@ class zcfsPostFilter extends adminGenericFilter
|
|||
$users = null;
|
||||
|
||||
try {
|
||||
$users = dcCore::app()->blog->getPostsUsers();
|
||||
if ($users->isEmpty()) {
|
||||
$users = dcCore::app()->blog?->getPostsUsers();
|
||||
if (is_null($users) || $users->isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
|
@ -81,8 +89,8 @@ class zcfsPostFilter extends adminGenericFilter
|
|||
$categories = null;
|
||||
|
||||
try {
|
||||
$categories = dcCore::app()->blog->getCategories();
|
||||
if ($categories->isEmpty()) {
|
||||
$categories = dcCore::app()->blog?->getCategories();
|
||||
if (is_null($categories) || $categories->isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
|
@ -96,10 +104,12 @@ class zcfsPostFilter extends adminGenericFilter
|
|||
__('(No cat)') => 'NULL',
|
||||
];
|
||||
while ($categories->fetch()) {
|
||||
if (is_numeric($categories->f('level')) && is_string($categories->f('cat_title'))) {
|
||||
$combo[
|
||||
str_repeat(' ', ($categories->level - 1) * 4) .
|
||||
html::escapeHTML($categories->cat_title) . ' (' . $categories->nb_post . ')'
|
||||
] = $categories->cat_id;
|
||||
str_repeat(' ', ((int) $categories->f('level') - 1) * 4) .
|
||||
Html::escapeHTML($categories->f('cat_title')) . ' (' . $categories->f('nb_post') . ')'
|
||||
] = $categories->f('cat_id');
|
||||
}
|
||||
}
|
||||
|
||||
return (new dcAdminFilter('cat_id'))
|
||||
|
@ -131,8 +141,8 @@ class zcfsPostFilter extends adminGenericFilter
|
|||
$dates = null;
|
||||
|
||||
try {
|
||||
$dates = dcCore::app()->blog->getDates(['type' => 'month']);
|
||||
if ($dates->isEmpty()) {
|
||||
$dates = dcCore::app()->blog?->getDates(['type' => 'month']);
|
||||
if (is_null($dates) || $dates->isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
|
|
|
@ -10,139 +10,173 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use adminGenericListV2;
|
||||
use dcCore;
|
||||
use dcPager;
|
||||
use Dotclear\Helper\Date;
|
||||
use Dotclear\Helper\Html\Form\{
|
||||
Checkbox,
|
||||
Div,
|
||||
Link,
|
||||
Para,
|
||||
Text
|
||||
};
|
||||
use Dotclear\Helper\Html\Html;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Feeds server - Posts list methods
|
||||
* @since 2.6
|
||||
* @see adminGenericList for more info
|
||||
* Backend feed posts lists.
|
||||
*/
|
||||
class zcfsEntriesList extends adminGenericList
|
||||
class PostsList extends adminGenericListV2
|
||||
{
|
||||
public function display($page, $nb_per_page, $base_url, $enclose_block = '', $filter = false)
|
||||
public function display(PostsFilter $filter, string $base_url, string $enclose_block = ''): void
|
||||
{
|
||||
if ($this->rs->isEmpty()) {
|
||||
echo '<p><strong>' . (
|
||||
$filter ?
|
||||
echo
|
||||
(new Text(
|
||||
'p',
|
||||
$filter->show() ?
|
||||
__('No entries matches the filter') :
|
||||
__('No entries')
|
||||
) . '</strong></p>';
|
||||
} else {
|
||||
$pager = new dcPager($page, $this->rs_count, $nb_per_page, 10);
|
||||
))
|
||||
->class('info')
|
||||
->render();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$page = is_numeric($filter->value('page')) ? (int) $filter->value('page') : 1;
|
||||
$nbpp = is_numeric($filter->value('nb')) ? (int) $filter->value('nb') : 10;
|
||||
$count = (int) $this->rs_count;
|
||||
$pager = new dcPager($page, $count, $nbpp, 10);
|
||||
$pager->base_url = $base_url;
|
||||
|
||||
$entries = [];
|
||||
if (isset($_REQUEST['feeds'])) {
|
||||
foreach ($_REQUEST['feeds'] as $v) {
|
||||
$entries[(int) $v] = true;
|
||||
}
|
||||
}
|
||||
$cols = new ArrayObject([
|
||||
'title' => (new Text('th', __('Title')))
|
||||
->class('first')
|
||||
->extra('colspan="2"'),
|
||||
'date' => (new Text('th', __('Date')))
|
||||
->extra('scope="col"'),
|
||||
'author' => (new Text('th', __('Author')))
|
||||
->extra('scope="col"'),
|
||||
'category' => (new Text('th', __('Category')))
|
||||
->extra('scope="col"'),
|
||||
'status' => (new Text('th', __('Status')))
|
||||
->extra('scope="col"'),
|
||||
]);
|
||||
|
||||
$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];
|
||||
$this->userColumns(My::id() . 'posts', $cols);
|
||||
|
||||
$lines = [];
|
||||
while ($this->rs->fetch()) {
|
||||
echo $this->postLine();
|
||||
$lines[] = $this->line(isset($_POST['entries']) && in_array($this->rs->post_id, $_POST['entries']));
|
||||
}
|
||||
|
||||
echo $blocks[1];
|
||||
|
||||
echo $pager->getLinks();
|
||||
}
|
||||
echo
|
||||
$pager->getLinks() .
|
||||
sprintf(
|
||||
$enclose_block,
|
||||
(new Div())
|
||||
->class('table-outer')
|
||||
->items([
|
||||
(new Para(null, 'table'))
|
||||
->items([
|
||||
(new Text(
|
||||
'caption',
|
||||
$filter->show() ?
|
||||
sprintf(__('List of %s entries matching the filter.'), $this->rs_count) :
|
||||
sprintf(__('List of entries. (%s)'), $this->rs_count)
|
||||
)),
|
||||
(new Para(null, 'tr'))
|
||||
->items(iterator_to_array($cols)),
|
||||
(new Para(null, 'tbody'))
|
||||
->items($lines),
|
||||
]),
|
||||
])
|
||||
->render()
|
||||
) .
|
||||
$pager->getLinks();
|
||||
}
|
||||
|
||||
private function postLine()
|
||||
private function line(bool $checked): Para
|
||||
{
|
||||
$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 = (new Text('', __('None')));
|
||||
if ($this->rs->cat_title
|
||||
&& dcCore::app()->auth?->check(dcCore::app()->auth->makePermissions([dcCore::app()->auth::PERMISSION_CATEGORIES]), dcCore::app()->blog?->id)
|
||||
) {
|
||||
$cat_title = (new Link())
|
||||
->href('category.php?id=' . $this->rs->cat_id)
|
||||
->title(Html::escapeHTML(__('Edit category')))
|
||||
->text(Html::escapeHTML($this->rs->cat_title));
|
||||
}
|
||||
|
||||
$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';
|
||||
$img_title = __('Published');
|
||||
$img_src = 'check-on.png';
|
||||
$sts_class = ' sts-online';
|
||||
|
||||
break;
|
||||
case -1:
|
||||
$img_status = sprintf($img, __('Scheduled'), 'scheduled.png');
|
||||
$sts_class = 'sts-scheduled';
|
||||
$img_title = __('Scheduled');
|
||||
$img_src = 'scheduled.png';
|
||||
$sts_class = ' sts-scheduled';
|
||||
|
||||
break;
|
||||
case -2:
|
||||
$img_status = sprintf($img, __('Pending'), 'check-wrn.png');
|
||||
$sts_class = 'sts-pending';
|
||||
$img_title = __('Pending');
|
||||
$img_src = 'check-wrn.png';
|
||||
$sts_class = ' sts-pending';
|
||||
|
||||
break;
|
||||
default:
|
||||
$img_title = __('Unpublished');
|
||||
$img_src = 'check-off.png';
|
||||
$sts_class = ' sts-offline';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$res = '<tr class="line ' . ($this->rs->post_status != 1 ? 'offline ' : '') . $sts_class . '"' .
|
||||
' id="p' . $this->rs->post_id . '">';
|
||||
$cols = new ArrayObject([
|
||||
'check' => (new Para(null, 'td'))
|
||||
->class('nowrap minimal')
|
||||
->items([
|
||||
(new Checkbox(['entries[]'], $checked))
|
||||
->value($this->rs->post_id)
|
||||
->disabled(!$this->rs->isEditable()),
|
||||
]),
|
||||
'title' => (new Para(null, 'td'))
|
||||
->class('maximal')
|
||||
->items([
|
||||
(new Link())
|
||||
->href(dcCore::app()->getPostAdminURL($this->rs->post_type, $this->rs->post_id))
|
||||
->title(Html::escapeHTML($this->rs->getURL()))
|
||||
->text(Html::escapeHTML(trim(Html::clean($this->rs->post_title)))),
|
||||
]),
|
||||
'date' => (new Text('td', Date::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->post_dt)))
|
||||
->class('nowrap count'),
|
||||
'author' => (new Text('td', Html::escapeHTML($this->rs->user_id)))
|
||||
->class('nowrap'),
|
||||
'category' => (new Para(null, 'td'))
|
||||
->class('nowrap')
|
||||
->items([$cat_title]),
|
||||
'status' => (new Para(null, 'td'))
|
||||
->class('nowrap status')
|
||||
->items([
|
||||
(new Text('img', ''))
|
||||
->title($img_title)
|
||||
->extra('src="images/' . $img_src . '"'),
|
||||
]),
|
||||
]);
|
||||
|
||||
$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>',
|
||||
];
|
||||
$this->userColumns(My::id() . 'posts', $cols);
|
||||
|
||||
$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;
|
||||
return (new Para('p' . $this->rs->post_id, 'tr'))
|
||||
->class('line' . ($this->rs->post_status != 1 ? ' offline ' : '') . $sts_class)
|
||||
->items(iterator_to_array($cols));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,35 +10,44 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
Clearbricks::lib()->autoload([
|
||||
'zoneclearFeedServer' => __DIR__ . '/inc/class.zoneclearfeedserver.php',
|
||||
'zcfsAdminBehaviors' => __DIR__ . '/inc/class.zcfsadminbehaviors.php',
|
||||
'zcfsPostFilter' => __DIR__ . '/inc/class.zcfspostfilter.php',
|
||||
'zcfsEntriesList' => __DIR__ . '/inc/class.zcfsentrieslist.php',
|
||||
'zcfsFeedsList' => __DIR__ . '/inc/class.zcfsfeedslist.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',
|
||||
'zcfsUpgrade' => __DIR__ . '/inc/class.zcfsupgrade.php',
|
||||
]);
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
// public url for page of description of the flux
|
||||
dcCore::app()->url->register(
|
||||
use dcCore;
|
||||
use dcNsProcess;
|
||||
|
||||
/**
|
||||
* Module prepend.
|
||||
*/
|
||||
class Prepend extends dcNsProcess
|
||||
{
|
||||
public static function init(): bool
|
||||
{
|
||||
static::$init = My::phpCompliant();
|
||||
|
||||
return static::$init;
|
||||
}
|
||||
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// public url for page of description of the flux
|
||||
dcCore::app()->url->register(
|
||||
'zoneclearFeedsPage',
|
||||
'zcfeeds',
|
||||
'^zcfeeds(.*?)$',
|
||||
['zcfsUrlHandler', 'zcFeedsPage']
|
||||
);
|
||||
[UrlHandler::class, 'zoneclearFeedsPage']
|
||||
);
|
||||
|
||||
// Add to report on plugin activityReport
|
||||
if (defined('ACTIVITY_REPORT_V2')) {
|
||||
zcfsActivityReportBehaviors::init();
|
||||
// report zoneclearFeedServer activities
|
||||
if (defined('ACTIVITY_REPORT') && ACTIVITY_REPORT == 3) {
|
||||
ActivityReportActions::init();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,74 +10,83 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use context;
|
||||
use dcCore;
|
||||
use rsExtPost;
|
||||
use rsExtPostPublic;
|
||||
use Dotclear\Database\MetaRecord;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Mix your blog with a feeds planet - rs methods.
|
||||
* @since 2.6
|
||||
* Posts record extension to integrate feed info.
|
||||
*/
|
||||
class zcfsRsExtPosts extends rsExtPost
|
||||
class RsExtPosts extends rsExtPost
|
||||
{
|
||||
public static function zc()
|
||||
{
|
||||
return new zoneclearFeedServer();
|
||||
}
|
||||
/** @var array<string,mixed> $brother_extensions Stack posts record extensions */
|
||||
public static array $brother_extensions = [];
|
||||
|
||||
/**
|
||||
* Get feed meta.
|
||||
*
|
||||
* @param dcRecord $rs record instance
|
||||
* @param string $info Feed info key
|
||||
* @return string Feed info value
|
||||
* @param MetaRecord $rs The record instance
|
||||
* @param string $info The feed info key
|
||||
*
|
||||
* @return null|string Feed info value
|
||||
*/
|
||||
public static function zcFeed($rs, $info)
|
||||
public static function zcFeed(MetaRecord $rs, string $info): ?string
|
||||
{
|
||||
$meta = dcCore::app()->meta->getMetadata([
|
||||
'post_id' => $rs->post_id,
|
||||
'meta_type' => 'zoneclearfeed_' . $info,
|
||||
'post_id' => $rs->f('post_id'),
|
||||
'meta_type' => My::META_PREFIX . $info,
|
||||
'limit' => 1,
|
||||
]);
|
||||
|
||||
return $meta->isEmpty() ? null : $meta->meta_id;
|
||||
return $meta->isEmpty() || !is_string($meta->f('meta_id')) ? null : $meta->f('meta_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Call other rs extension.
|
||||
*
|
||||
* @param string $type Type of extension
|
||||
* @param array $args Arguments
|
||||
* @return mixed record extension ressource
|
||||
* @param string $type The type of extension
|
||||
* @param array<string|int,mixed> $args The arguments
|
||||
*
|
||||
* @return string The record extension ressource result
|
||||
*/
|
||||
public static function zcFeedBrother($type, $args)
|
||||
public static function zcFeedBrother(string $type, array $args): string
|
||||
{
|
||||
$ext = dcCore::app()->__get('beforeZcFeedRsExt');
|
||||
if (null !== $ext && !empty($ext[$type])) {
|
||||
$ext = static::$brother_extensions;
|
||||
if (isset($ext[$type]) && is_callable($ext[$type])) {
|
||||
$func = $ext[$type];
|
||||
} elseif (is_callable(['rsExtPostPublic', $type])) {
|
||||
$func = ['rsExtPostPublic', $type];
|
||||
} elseif (is_callable([rsExtPostPublic::class, $type])) {
|
||||
$func = [rsExtPostPublic::class, $type];
|
||||
} elseif (is_callable([rsExtPost::class, $type])) {
|
||||
$func = [rsExtPost::class, $type];
|
||||
} else {
|
||||
$func = ['rsExtPost', $type];
|
||||
return '';
|
||||
}
|
||||
|
||||
return call_user_func_array($func, $args);
|
||||
$cb = call_user_func_array($func, $args);
|
||||
|
||||
return is_string($cb) ? $cb : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get author link from post to feed.
|
||||
*
|
||||
* @param dcRecord $rs record instance
|
||||
* @return string Author link
|
||||
* @param MetaRecord $rs The record instance
|
||||
* @return string The author link
|
||||
*/
|
||||
public static function getAuthorLink(dcRecord $rs): string
|
||||
public static function getAuthorLink(MetaRecord $rs): string
|
||||
{
|
||||
$author = $rs->zcFeed('author');
|
||||
$site = $rs->zcFeed('site');
|
||||
$sitename = $rs->zcFeed('sitename');
|
||||
$author = $rs->__call('zcFeed', ['author']);
|
||||
$site = $rs->__call('zcFeed', ['site']);
|
||||
$sitename = $rs->__call('zcFeed', ['sitename']);
|
||||
|
||||
return $author && $sitename ?
|
||||
return is_string($author) && is_string($site) && is_string($sitename) ?
|
||||
sprintf('%s (<a href="%s">%s</a>)', $author, $site, $sitename) :
|
||||
self::zcFeedBrother('getAuthorLink', [&$rs]);
|
||||
}
|
||||
|
@ -85,14 +94,15 @@ class zcfsRsExtPosts extends rsExtPost
|
|||
/**
|
||||
* Get author CN from post to feed.
|
||||
*
|
||||
* @param dcRecord $rs record instance
|
||||
* @return string Author CN
|
||||
* @param MetaRecord $rs The record instance
|
||||
*
|
||||
* @return string The author CN
|
||||
*/
|
||||
public static function getAuthorCN(dcRecord $rs): string
|
||||
public static function getAuthorCN(MetaRecord $rs): string
|
||||
{
|
||||
$author = $rs->zcFeed('author');
|
||||
$author = $rs->__call('zcFeed', ['author']);
|
||||
|
||||
return $author ?
|
||||
return is_string($author) ?
|
||||
$author :
|
||||
self::zcFeedBrother('getAuthorCN', [&$rs]);
|
||||
}
|
||||
|
@ -100,36 +110,37 @@ class zcfsRsExtPosts extends rsExtPost
|
|||
/**
|
||||
* Get post link from post to feed.
|
||||
*
|
||||
* @param dcRecord $rs record instance
|
||||
* @return string Post link
|
||||
* @param MetaRecord $rs The record instance
|
||||
*
|
||||
* @return string The post link
|
||||
*/
|
||||
public static function getURL(dcRecord $rs): string
|
||||
public static function getURL(MetaRecord $rs): string
|
||||
{
|
||||
$url = $rs->zcFeed('url');
|
||||
$types = json_decode(dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)))->post_title_redir);
|
||||
$full = is_array($types) && in_array(dcCore::app()->url->type, $types);
|
||||
$url = $rs->__call('zcFeed', ['url']);
|
||||
$site = $rs->__call('zcFeed', ['site']);
|
||||
$full = in_array(dcCore::app()->url->type, ZoneclearFeedServer::instance()->settings->post_title_redir);
|
||||
|
||||
return $url && $full ?
|
||||
zoneclearFeedServer::absoluteURL($rs->zcFeed('site'), $url) :
|
||||
return is_string($site) && is_string($url) && $full ?
|
||||
ZoneclearFeedServer::instance()::absoluteURL($site, $url) :
|
||||
self::zcFeedBrother('getURL', [&$rs]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post content from post to feed.
|
||||
*
|
||||
* @param dcRecord $rs record instance
|
||||
* @return string Post content
|
||||
* @param MetaRecord $rs The record instance
|
||||
* @param mixed $absolute_urls Serve absolute URL (type "mixed" from rsExtPost)
|
||||
*
|
||||
* @return string The post content
|
||||
*/
|
||||
public static function getContent(dcRecord $rs, bool $absolute_urls = false): string
|
||||
public static function getContent(MetaRecord $rs, mixed $absolute_urls = false): string
|
||||
{
|
||||
$url = $rs->zcFeed('url');
|
||||
$sitename = $rs->zcFeed('sitename');
|
||||
$url = $rs->__call('zcFeed', ['url']);
|
||||
$sitename = $rs->__call('zcFeed', ['sitename']);
|
||||
$content = self::zcFeedBrother('getContent', [&$rs, $absolute_urls]);
|
||||
|
||||
if ($url && $sitename && $rs->post_type == 'post') {
|
||||
$types = json_decode(dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)))->post_full_tpl);
|
||||
|
||||
if (is_array($types) && in_array(dcCore::app()->url->type, $types)) {
|
||||
if (is_string($url) && is_string($sitename) && $rs->f('post_type') == 'post') {
|
||||
if (in_array(dcCore::app()->url->type, ZoneclearFeedServer::instance()->settings->post_full_tpl)) {
|
||||
return $content . sprintf(
|
||||
'<p class="zoneclear-original"><em>%s</em></p>',
|
||||
sprintf(__('Original post on <a href="%s">%s</a>'), $url, $sitename)
|
||||
|
@ -137,7 +148,7 @@ class zcfsRsExtPosts extends rsExtPost
|
|||
}
|
||||
$content = context::remove_html($content);
|
||||
$content = context::cut_string($content, 350);
|
||||
$content = html::escapeHTML($content);
|
||||
$content = Html::escapeHTML($content);
|
||||
|
||||
return sprintf(
|
||||
'<p>%s... <em><a href="%s" title="%s">%s</a></em></p>',
|
||||
|
|
125
src/Settings.php
Normal file
125
src/Settings.php
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Module settings (type hinting).
|
||||
*/
|
||||
class Settings
|
||||
{
|
||||
/** @var Settings Self instance */
|
||||
private static $instance;
|
||||
|
||||
public readonly bool $active;
|
||||
|
||||
public readonly bool $pub_active;
|
||||
|
||||
public readonly bool $post_status_new;
|
||||
|
||||
public readonly int $bhv_pub_upd;
|
||||
|
||||
public readonly int $update_limit;
|
||||
|
||||
public readonly bool $keep_empty_feed;
|
||||
|
||||
public readonly int $tag_case;
|
||||
|
||||
/** @var array<int,string> */
|
||||
public readonly array $post_full_tpl;
|
||||
|
||||
/** @var array<int,string> */
|
||||
public readonly array $post_title_redir;
|
||||
|
||||
public readonly string $user;
|
||||
|
||||
/**
|
||||
* Constructor set up plugin settings.
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
if (is_null(dcCore::app()->blog)) {
|
||||
throw new Exception(__('Blog is not defined'));
|
||||
}
|
||||
|
||||
$s = dcCore::app()->blog->settings->get(My::id());
|
||||
|
||||
$update_limit = is_numeric($s->get('update_limit')) ? (int) $s->get('update_limit') : 1;
|
||||
|
||||
$this->active = !empty($s->get('active'));
|
||||
$this->pub_active = !empty($s->get('pub_active'));
|
||||
$this->post_status_new = !empty($s->get('post_status_new'));
|
||||
$this->bhv_pub_upd = is_numeric($s->get('bhv_pub_upd')) ? (int) $s->get('bhv_pub_upd') : 1;
|
||||
$this->update_limit = $update_limit < 1 ? 10 : $update_limit;
|
||||
$this->keep_empty_feed = !empty($s->get('keep_empty_feed'));
|
||||
$this->tag_case = is_numeric($s->get('tag_case')) ? (int) $s->get('tag_case') : 0;
|
||||
$this->post_full_tpl = is_array($s->get('post_full_tpl')) ? $s->get('post_full_tpl') : [];
|
||||
$this->post_title_redir = is_array($s->get('post_title_redir')) ? $s->get('post_title_redir') : [];
|
||||
$this->user = is_string($s->get('user')) ? $s->get('user') : '';
|
||||
}
|
||||
|
||||
public static function instance(): Settings
|
||||
{
|
||||
if (!(self::$instance instanceof Settings)) {
|
||||
self::$instance = new Settings();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function isset(string $key): bool
|
||||
{
|
||||
return property_exists($this, $key);
|
||||
}
|
||||
|
||||
public function get(string $key): mixed
|
||||
{
|
||||
return $this->{$key} ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite a plugin settings (in db).
|
||||
*
|
||||
* @param string $key The setting ID
|
||||
* @param mixed $value The setting value
|
||||
*
|
||||
* @return bool True on success
|
||||
*/
|
||||
public function set(string $key, mixed $value): bool
|
||||
{
|
||||
$s = dcCore::app()->blog?->settings->get(My::id());
|
||||
|
||||
if (!is_null($s) && property_exists($this, $key) && settype($value, gettype($this->{$key})) === true) {
|
||||
$s->drop($key);
|
||||
$s->put($key, $value, gettype($this->{$key}), '', true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* List defined settings keys.
|
||||
*
|
||||
* @return array<string,mixed> The settings keys
|
||||
*/
|
||||
public function dump(): array
|
||||
{
|
||||
return get_object_vars($this);
|
||||
}
|
||||
}
|
176
src/Template.php
176
src/Template.php
|
@ -10,44 +10,47 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use dcCore;
|
||||
use dcTemplate;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Mix your blog with a feeds planet - template methods.
|
||||
* @since 2.6
|
||||
* Frontend template blocks and values.
|
||||
*/
|
||||
class zcfsTemplate
|
||||
class Template
|
||||
{
|
||||
public static function Feeds($a, $c)
|
||||
public static function Feeds(ArrayObject $a, string $c): string
|
||||
{
|
||||
$lastn = -1;
|
||||
$p = '';
|
||||
if (isset($a['lastn'])) {
|
||||
if (isset($a['lastn']) && is_numeric($a['lastn'])) {
|
||||
$lastn = abs((int) $a['lastn']) + 0;
|
||||
$p .= "\$zcfs_params['limit'] = " . $lastn . ";\n";
|
||||
}
|
||||
if (isset($a['cat_id'])) {
|
||||
if (isset($a['cat_id']) && is_string($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'])) {
|
||||
if (!empty($a['site_url']) && is_string($a['site_url'])) {
|
||||
$p .= "\$zcfs_params['feed_url'] = '" . addslashes($a['site_url']) . "';\n";
|
||||
}
|
||||
if (isset($a['feed_status'])) {
|
||||
if (isset($a['feed_status']) && is_numeric($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'])) {
|
||||
if (!empty($a['feed_url']) && is_string($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";
|
||||
if (isset($a['feed_owner']) && is_string($a['feed_owner'])) {
|
||||
$p .= "@\$zcfs_params['sql'] .= \"AND Z.feed_owner = '" . addslashes($a['feed_owner']) . "' \";\n";
|
||||
}
|
||||
|
||||
$sortby = 'feed_creadt';
|
||||
|
@ -71,7 +74,7 @@ class zcfsTemplate
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (isset($a['order']) && preg_match('/^(desc|asc)$/i', $a['order'])) {
|
||||
if (isset($a['order']) && is_string($a['order']) && preg_match('/^(desc|asc)$/i', $a['order'])) {
|
||||
$order = $a['order'];
|
||||
}
|
||||
$p .= "\$zcfs_params['order'] = '" . $sortby . ' ' . $order . "';\n";
|
||||
|
@ -79,26 +82,26 @@ class zcfsTemplate
|
|||
return
|
||||
'<?php ' . $p .
|
||||
'dcCore::app()->ctx->feeds_params = $zcfs_params;' . "\n" .
|
||||
'$zcfs = new zoneclearFeedServer();' . "\n" .
|
||||
'$zcfs = ' . ZoneclearFeedServer::class . '::instance();' . "\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)
|
||||
public static function FeedIf(ArrayObject $a, string $c): string
|
||||
{
|
||||
$if = [];
|
||||
|
||||
$operator = isset($a['operator']) ? self::getOperator($a['operator']) : '&&';
|
||||
$operator = isset($a['operator']) && is_string($a['operator']) ? dcTemplate::getOperator($a['operator']) : '&&';
|
||||
|
||||
if (isset($a['type'])) {
|
||||
if (isset($a['type']) && is_string($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 (isset($a['site_url']) && is_string($a['site_url'])) {
|
||||
$url = trim($a['site_url']);
|
||||
if (substr($url, 0, 1) == '!') {
|
||||
$url = substr($url, 1);
|
||||
$if[] = 'dcCore::app()->ctx->feeds->feed_url != "' . addslashes($url) . '"';
|
||||
|
@ -106,8 +109,8 @@ class zcfsTemplate
|
|||
$if[] = 'dcCore::app()->ctx->feeds->feed_url == "' . addslashes($url) . '"';
|
||||
}
|
||||
}
|
||||
if (isset($a['feed_url'])) {
|
||||
$url = trim($a['feed_feed']);
|
||||
if (isset($a['feed_url']) && is_string($a['feed_url'])) {
|
||||
$url = trim($a['feed_url']);
|
||||
if (substr($url, 0, 1) == '!') {
|
||||
$url = substr($url, 1);
|
||||
$if[] = 'dcCore::app()->ctx->feeds->feed_feed != "' . addslashes($url) . '"';
|
||||
|
@ -115,7 +118,7 @@ class zcfsTemplate
|
|||
$if[] = 'dcCore::app()->ctx->feeds->feed_feed == "' . addslashes($url) . '"';
|
||||
}
|
||||
}
|
||||
if (isset($a['category'])) {
|
||||
if (isset($a['category']) && is_string($a['category'])) {
|
||||
$category = addslashes(trim($a['category']));
|
||||
if (substr($category, 0, 1) == '!') {
|
||||
$category = substr($category, 1);
|
||||
|
@ -146,112 +149,100 @@ class zcfsTemplate
|
|||
'<?php if(' . implode(' ' . $operator . ' ', $if) . ') : ?>' . $c . '<?php endif; ?>';
|
||||
}
|
||||
|
||||
public static function FeedIfFirst($a)
|
||||
public static function FeedIfFirst(ArrayObject $a): string
|
||||
{
|
||||
$ret = $a['return'] ?? 'first';
|
||||
$ret = html::escapeHTML($ret);
|
||||
$ret = Html::escapeHTML(isset($a['return']) && is_string($a['return']) ? $a['return'] : 'first');
|
||||
|
||||
return
|
||||
'<?php if (dcCore::app()->ctx->feeds->index() == 0) { ' .
|
||||
"echo '" . addslashes($ret) . "'; } ?>";
|
||||
}
|
||||
|
||||
public static function FeedIfOdd($a)
|
||||
public static function FeedIfOdd(ArrayObject $a): string
|
||||
{
|
||||
$ret = $a['return'] ?? 'odd';
|
||||
$ret = html::escapeHTML($ret);
|
||||
$ret = Html::escapeHTML(isset($a['return']) && is_string($a['return']) ? $a['return'] : 'odd');
|
||||
|
||||
return
|
||||
'<?php if ((dcCore::app()->ctx->feeds->index()+1)%2 == 1) { ' .
|
||||
"echo '" . addslashes($ret) . "'; } ?>";
|
||||
}
|
||||
|
||||
public static function FeedDesc($a)
|
||||
public static function FeedDesc(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_desc');
|
||||
}
|
||||
|
||||
public static function FeedOwner($a)
|
||||
public static function FeedOwner(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_owner');
|
||||
}
|
||||
|
||||
public static function FeedCategory($a)
|
||||
public static function FeedCategory(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_title');
|
||||
}
|
||||
|
||||
public static function FeedCategoryID($a)
|
||||
public static function FeedCategoryID(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_id');
|
||||
}
|
||||
|
||||
public static function FeedCategoryURL($a)
|
||||
public static function FeedCategoryURL(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->blog->url.dcCore::app()->url->getBase(\'category\').\'/\'.html::sanitizeURL(dcCore::app()->ctx->feeds->cat_url)');
|
||||
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)
|
||||
public static function FeedCategoryShortURL(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->cat_url');
|
||||
}
|
||||
|
||||
public static function FeedID($a)
|
||||
public static function FeedID(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_id');
|
||||
}
|
||||
|
||||
public static function FeedLang($a)
|
||||
public static function FeedLang(ArrayObject $a): string
|
||||
{
|
||||
$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); ?>';
|
||||
self::getValue($a, 'dcCore::app()->ctx->feeds->feed_lang') :
|
||||
'<?php $langs = l10n::getISOcodes(); if (isset($langs[dcCore::app()->ctx->feeds->feed_lang])) { ?>' .
|
||||
self::getValue($a, '$langs[dcCore::app()->ctx->feeds->feed_lang]') .
|
||||
'<?php } else { ?>' .
|
||||
self::getValue($a, 'dcCore::app()->ctx->feeds->feed_lang') .
|
||||
'<?php ; } unset($langs); ?>';
|
||||
}
|
||||
|
||||
public static function FeedName($a)
|
||||
public static function FeedName(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_name');
|
||||
}
|
||||
|
||||
public static function FeedSiteURL($a)
|
||||
public static function FeedSiteURL(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_url');
|
||||
}
|
||||
|
||||
public static function FeedFeedURL($a)
|
||||
public static function FeedFeedURL(ArrayObject $a): string
|
||||
{
|
||||
return self::getValue($a, 'dcCore::app()->ctx->feeds->feed_feed');
|
||||
}
|
||||
|
||||
public static function FeedsHeader($a, $c)
|
||||
public static function FeedsHeader(ArrayObject $a, string $c): string
|
||||
{
|
||||
return '<?php if (dcCore::app()->ctx->feeds->isStart()) : ?>' . $c . '<?php endif; ?>';
|
||||
}
|
||||
|
||||
public static function FeedsFooter($a, $c)
|
||||
public static function FeedsFooter(ArrayObject $a, string $c): string
|
||||
{
|
||||
return '<?php if (dcCore::app()->ctx->feeds->isEnd()) : ?>' . $c . '<?php endif; ?>';
|
||||
}
|
||||
|
||||
public static function FeedsCount($a)
|
||||
public static function FeedsCount(ArrayObject $a): string
|
||||
{
|
||||
$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']);
|
||||
}
|
||||
$none = isset($a['none']) && is_string($a['none']) ? addslashes($a['none']) : 'no sources';
|
||||
$one = isset($a['one']) && is_string($a['one']) ? addslashes($a['one']) : 'one source';
|
||||
$more = isset($a['more']) && is_string($a['more']) ? addslashes($a['more']) : '%d sources';
|
||||
|
||||
return
|
||||
"<?php \$fcount = dcCore::app()->ctx->feeds->count(); \n" .
|
||||
|
@ -264,25 +255,15 @@ class zcfsTemplate
|
|||
'} unset($fcount); ?>';
|
||||
}
|
||||
|
||||
public static function FeedsEntriesCount($a)
|
||||
public static function FeedsEntriesCount(ArrayObject $a): string
|
||||
{
|
||||
$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']);
|
||||
}
|
||||
$none = isset($a['none']) && is_string($a['none']) ? addslashes($a['none']) : 'no entries';
|
||||
$one = isset($a['one']) && is_string($a['one']) ? addslashes($a['one']) : 'one entry';
|
||||
$more = isset($a['more']) && is_string($a['more']) ? addslashes($a['more']) : '%d entries';
|
||||
|
||||
return
|
||||
"<?php \$fcount = 0; \n" .
|
||||
'$zc = new zoneclearFeedServer();' . "\n" .
|
||||
'$zc = ' . ZoneclearFeedServer::class . '::instance();' . "\n" .
|
||||
"\$allfeeds = \$zc->getFeeds(); \n" .
|
||||
"if (!\$allfeeds->isEmpty()) { \n" .
|
||||
' while ($allfeeds->fetch()) { ' .
|
||||
|
@ -298,24 +279,14 @@ class zcfsTemplate
|
|||
'} unset($allfeeds,$fcount); ?>';
|
||||
}
|
||||
|
||||
public static function FeedEntriesCount($a)
|
||||
public static function FeedEntriesCount(ArrayObject $a): string
|
||||
{
|
||||
$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']);
|
||||
}
|
||||
$none = isset($a['none']) && is_string($a['none']) ? addslashes($a['none']) : 'no entries';
|
||||
$one = isset($a['one']) && is_string($a['one']) ? addslashes($a['one']) : 'one entry';
|
||||
$more = isset($a['more']) && is_string($a['more']) ? addslashes($a['more']) : '%d entries';
|
||||
|
||||
return
|
||||
"<?php \$zcfs = new zoneclearFeedServer(); \n" .
|
||||
'<?php $zcfs = ' . ZoneclearFeedServer::class . "::instance(); \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" .
|
||||
|
@ -326,21 +297,8 @@ class zcfsTemplate
|
|||
'} unset($fcount); ?>';
|
||||
}
|
||||
|
||||
protected static function getValue($a, $v)
|
||||
protected static function getValue(ArrayObject $a, string $v): string
|
||||
{
|
||||
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 '&&';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,102 +10,89 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
$this->addUserAction(
|
||||
/* type */
|
||||
'settings',
|
||||
/* action */
|
||||
'delete_all',
|
||||
/* ns */
|
||||
basename(__DIR__),
|
||||
/* desc */
|
||||
__('delete all settings')
|
||||
);
|
||||
$this->addUserAction(
|
||||
/* type */
|
||||
'tables',
|
||||
/* action */
|
||||
'delete',
|
||||
/* ns */
|
||||
initZoneclearFeedServer::TABLE_NAME,
|
||||
/* desc */
|
||||
__('delete table')
|
||||
);
|
||||
$this->addUserAction(
|
||||
/* type */
|
||||
'plugins',
|
||||
/* action */
|
||||
'delete',
|
||||
/* ns */
|
||||
basename(__DIR__),
|
||||
/* desc */
|
||||
__('delete plugin files')
|
||||
);
|
||||
$this->addUserAction(
|
||||
/* type */
|
||||
'versions',
|
||||
/* action */
|
||||
'delete',
|
||||
/* ns */
|
||||
basename(__DIR__),
|
||||
/* desc */
|
||||
__('delete the version number')
|
||||
);
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
$this->addDirectAction(
|
||||
/* type */
|
||||
'settings',
|
||||
/* action */
|
||||
'delete_all',
|
||||
/* ns */
|
||||
basename(__DIR__),
|
||||
/* desc */
|
||||
sprintf(__('delete all %s settings'), basename(__DIR__))
|
||||
);
|
||||
$this->addDirectAction(
|
||||
/* type */
|
||||
'tables',
|
||||
/* action */
|
||||
'delete',
|
||||
/* ns */
|
||||
initZoneclearFeedServer::TABLE_NAME,
|
||||
/* desc */
|
||||
sprintf(__('delete %s table'), basename(__DIR__))
|
||||
);
|
||||
$this->addDirectAction(
|
||||
/* type */
|
||||
'plugins',
|
||||
/* action */
|
||||
'delete',
|
||||
/* ns */
|
||||
basename(__DIR__),
|
||||
/* desc */
|
||||
sprintf(__('delete %s plugin files'), basename(__DIR__))
|
||||
);
|
||||
$this->addDirectAction(
|
||||
/* type */
|
||||
'versions',
|
||||
/* action */
|
||||
'delete',
|
||||
/* ns */
|
||||
basename(__DIR__),
|
||||
/* desc */
|
||||
sprintf(__('delete %s version number'), basename(__DIR__))
|
||||
);
|
||||
$this->addDirectCallback(
|
||||
/* function */
|
||||
'zoneclearfeedServerUninstall',
|
||||
/* desc */
|
||||
'delete feeds relations'
|
||||
);
|
||||
use dcCore;
|
||||
use dcNsProcess;
|
||||
use Dotclear\Plugin\Uninstaller\Uninstaller;
|
||||
|
||||
function zoneclearfeedServerUninstall($id)
|
||||
/**
|
||||
* Plugin Uninstaller actions.
|
||||
*/
|
||||
class Uninstall extends dcNsProcess
|
||||
{
|
||||
if ($id != basename(__DIR__)) {
|
||||
return null;
|
||||
public static function init(): bool
|
||||
{
|
||||
static::$init = defined('DC_CONTEXT_ADMIN');
|
||||
|
||||
return static::$init;
|
||||
}
|
||||
|
||||
public static function process(): bool
|
||||
{
|
||||
if (!static::$init || !dcCore::app()->plugins->moduleExists('Uninstaller')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($_POST[My::id() . 'DeletePostsMeta'])) {
|
||||
ZoneclearFeedServer::instance()::deletePostsMeta(null);
|
||||
}
|
||||
|
||||
Uninstaller::instance()
|
||||
->addUserAction(
|
||||
'settings',
|
||||
'delete_all',
|
||||
My::id()
|
||||
)
|
||||
->addUserAction(
|
||||
My::id() . 'DeletePostsMeta',
|
||||
'delete_all',
|
||||
My::id()
|
||||
)
|
||||
->addUserAction(
|
||||
'tables',
|
||||
'delete',
|
||||
My::TABLE_NAME
|
||||
)
|
||||
->addUserAction(
|
||||
'plugins',
|
||||
'delete',
|
||||
My::id()
|
||||
)
|
||||
->addUserAction(
|
||||
'versions',
|
||||
'delete',
|
||||
My::id()
|
||||
)
|
||||
->addDirectAction(
|
||||
'settings',
|
||||
'delete_all',
|
||||
My::id()
|
||||
)
|
||||
->addDirectAction(
|
||||
My::id() . 'DeletePostsMeta',
|
||||
'delete_all',
|
||||
My::id()
|
||||
)
|
||||
->addDirectAction(
|
||||
'tables',
|
||||
'delete',
|
||||
My::TABLE_NAME
|
||||
)
|
||||
->addDirectAction(
|
||||
'plugins',
|
||||
'delete',
|
||||
My::id()
|
||||
)
|
||||
->addDirectAction(
|
||||
'versions',
|
||||
'delete',
|
||||
My::id()
|
||||
)
|
||||
;
|
||||
|
||||
return false;
|
||||
}
|
||||
//...
|
||||
}
|
||||
|
|
104
src/UninstallCleaner.php
Normal file
104
src/UninstallCleaner.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use dcMeta;
|
||||
use Dotclear\Database\Statement\{
|
||||
DeleteStatement,
|
||||
SelectStatement
|
||||
};
|
||||
use Dotclear\Plugin\Uninstaller\{
|
||||
ActionDescriptor,
|
||||
CleanerDescriptor,
|
||||
CleanerParent,
|
||||
CleanersStack,
|
||||
ValueDescriptor
|
||||
};
|
||||
|
||||
/**
|
||||
* Plugin Uninstaller Cleaner object.
|
||||
*
|
||||
* This add special action for feed posts metadata.
|
||||
*/
|
||||
class UninstallCleaner extends CleanerParent
|
||||
{
|
||||
public static function init(CleanersStack $cleaners): void
|
||||
{
|
||||
$cleaners->set(new UninstallCleaner());
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new CleanerDescriptor(
|
||||
id: My::id() . 'DeletePostsMeta',
|
||||
name: __('Feed Server'),
|
||||
desc: __('Feed server posts feed metadata'),
|
||||
actions: [
|
||||
new ActionDescriptor(
|
||||
id: 'delete_all',
|
||||
select: __('delete selected posts feed metadata'),
|
||||
query: __('delete "%s" posts feed metadata'),
|
||||
success: __('"%s" posts feed metadata deleted'),
|
||||
error: __('Failed to delete "%s" posts feed metadata')
|
||||
),
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
public function distributed(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function values(): array
|
||||
{
|
||||
$sql = new SelectStatement();
|
||||
$sql->from(dcCore::app()->prefix . dcMeta::META_TABLE_NAME)
|
||||
->columns([
|
||||
$sql->as($sql->count('*'), 'counter'),
|
||||
])
|
||||
->where($sql->like('meta_type', My::META_PREFIX . '%'));
|
||||
|
||||
$rs = $sql->select();
|
||||
if (is_null($rs) || $rs->isEmpty() || !is_numeric($rs->f('counter'))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$res = [];
|
||||
while ($rs->fetch()) {
|
||||
$res[] = new ValueDescriptor(
|
||||
ns: My::id(),
|
||||
count: (int) $rs->f('counter')
|
||||
);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function execute(string $action, string $ns): bool
|
||||
{
|
||||
if ($action == 'delete_all') {
|
||||
$sql = new DeleteStatement();
|
||||
$sql->from(dcCore::app()->prefix . dcMeta::META_TABLE_NAME)
|
||||
->where($sql->like('meta_type', My::META_PREFIX . '%'))
|
||||
->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -10,27 +10,46 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
class zcfsUpgrade
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use dcNamespace;
|
||||
use Dotclear\Database\Statement\{
|
||||
SelectStatement,
|
||||
UpdateStatement
|
||||
};
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Module versions upgrades.
|
||||
*/
|
||||
class Upgrade
|
||||
{
|
||||
public static function preUpgrade()
|
||||
public static function preUpgrade(): void
|
||||
{
|
||||
$current = dcCore::app()->getVersion(basename(dirname('../' . __DIR__)));
|
||||
if ($current && version_compare($current, '2022.12.10', '<')) {
|
||||
$current = dcCore::app()->getVersion(My::id());
|
||||
if (!is_string($current) || empty($current)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (version_compare($current, '2022.12.10', '<')) {
|
||||
self::preUpgrade20221210();
|
||||
}
|
||||
|
||||
if (version_compare($current, '2023.05.05', '<')) {
|
||||
self::preUpgrade20230505();
|
||||
}
|
||||
}
|
||||
|
||||
protected static function preUpgrade20221210()
|
||||
protected static function preUpgrade20221210(): void
|
||||
{
|
||||
// Rename settings
|
||||
$setting_ids = [
|
||||
'zoneclearFeedServer_active' => 'active',
|
||||
'zoneclearFeedServer_pub_active' => 'pub_active',
|
||||
'zoneclearFeedServer_post_status_new' => 'psot_new_status',
|
||||
'zoneclearFeedServer_post_status_new' => 'post_new_status',
|
||||
'zoneclearFeedServer_bhv_pub_upd' => 'bhv_pub_upd',
|
||||
'zoneclearFeedServer_update_limit' => 'update_limit',
|
||||
'zoneclearFeedServer_keep_empty_feed' => 'keep_empty_feed',
|
||||
|
@ -40,23 +59,36 @@ class zcfsUpgrade
|
|||
'zoneclearFeedServer_post_title_redir' => 'post_title_redir',
|
||||
];
|
||||
|
||||
foreach ($setting_ids as $old => $new) {
|
||||
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME);
|
||||
$cur->setting_id = $new;
|
||||
$cur->update("WHERE setting_id = '" . $old . "' and setting_ns = 'zoneclearFeedServer' ");
|
||||
foreach ($setting_ids as $old => $new) {
|
||||
$cur->clean();
|
||||
$cur->setField('setting_id', $new);
|
||||
$cur->setField('setting_ns', My::id());
|
||||
|
||||
$sql = new UpdateStatement();
|
||||
$sql
|
||||
->where('setting_id = ' . $sql->quote($old))
|
||||
->and('setting_ns = ' . $sql->quote('zoneclearFeedServer'))
|
||||
->update();
|
||||
}
|
||||
|
||||
// use json rather than serialise for settings array
|
||||
$sql = new SelectStatement();
|
||||
$record = $sql
|
||||
->from(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME)
|
||||
->where('setting_ns = ' . $sql->quote(My::id()))
|
||||
->select();
|
||||
|
||||
if (is_null($record)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$setting_values = [
|
||||
'post_full_tpl' => ['post', 'category', 'tag', 'archive'],
|
||||
'post_title_redir' => ['feed'],
|
||||
];
|
||||
|
||||
$record = dcCore::app()->con->select(
|
||||
'SELECT * FROM ' . dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME . ' ' .
|
||||
"WHERE setting_ns = '" . dcCore::app()->con->escape(basename(dirname('../' . __DIR__))) . "' "
|
||||
);
|
||||
|
||||
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME);
|
||||
while ($record->fetch()) {
|
||||
foreach ($setting_values as $key => $default) {
|
||||
try {
|
||||
|
@ -65,13 +97,31 @@ class zcfsUpgrade
|
|||
$value = $default;
|
||||
}
|
||||
|
||||
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME);
|
||||
$cur->setting_value = json_encode(!is_array($value) ? $default : $value);
|
||||
$cur->update(
|
||||
"WHERE setting_id = '" . $key . "' and setting_ns = '" . dcCore::app()->con->escape($record->setting_ns) . "' " .
|
||||
'AND blog_id ' . (null === $record->blog_id ? 'IS NULL ' : ("= '" . dcCore::app()->con->escape($record->blog_id) . "' "))
|
||||
);
|
||||
$cur->clean();
|
||||
$cur->setField('setting_value', json_encode(!is_array($value) ? $default : $value));
|
||||
|
||||
$sql = new UpdateStatement();
|
||||
$sql
|
||||
->where('setting_id = ' . $sql->quote($key))
|
||||
->and('setting_ns = ' . $sql->quote($record->f('setting_ns')))
|
||||
->and('blog_id ' . (null === $record->f('blog_id') ? 'IS NULL ' : ('= ' . $sql->quote($record->f('blog_id')))))
|
||||
->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static function preUpgrade20230505(): void
|
||||
{
|
||||
// change settings type of json string to array
|
||||
$sql = new UpdateStatement();
|
||||
$sql
|
||||
->ref(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME)
|
||||
->column('setting_type')
|
||||
->value('array')
|
||||
->where('setting_id ' . $sql->in([
|
||||
'post_full_tpl',
|
||||
'post_title_redir',
|
||||
]))
|
||||
->update();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,41 +10,44 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use dcUrlHandlers;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Mix your blog with a feeds planet - url handler methods.
|
||||
* @since 2.6
|
||||
* Frontend URL handler.
|
||||
*
|
||||
* This adds public page that list feeds.
|
||||
* And serve an endpoint to update feeds through js.
|
||||
*/
|
||||
class zcfsUrlHandler extends dcUrlHandlers
|
||||
class UrlHandler extends dcUrlHandlers
|
||||
{
|
||||
/**
|
||||
* Feeds source page and update methods.
|
||||
*
|
||||
* @param array $args Page arguments
|
||||
* @return mixed
|
||||
* @param string $args The page arguments
|
||||
*/
|
||||
public static function zcFeedsPage($args)
|
||||
public static function zoneclearFeedsPage(string $args): void
|
||||
{
|
||||
$s = dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)));
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
|
||||
# Not active
|
||||
if (!$s->active) {
|
||||
if (is_null(dcCore::app()->blog) || !$s->active) {
|
||||
self::p404();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
# Update feeds (from ajax or other post resquest)
|
||||
if ($args == '/zcfsupd' && 3 == $s->bhv_pub_upd) {
|
||||
$msg = '';
|
||||
if (!empty($_POST['blogId']) && html::escapeJS(dcCore::app()->blog->id) == $_POST['blogId']) {
|
||||
if (!empty($_POST['blogId']) && Html::escapeJS(dcCore::app()->blog->id) == $_POST['blogId']) {
|
||||
try {
|
||||
$zc = new zoneclearFeedServer();
|
||||
if ($zc->checkFeedsUpdate()) {
|
||||
if ($z->checkFeedsUpdate()) {
|
||||
$msg = sprintf(
|
||||
'<status>%s</status><message>%s</message>',
|
||||
'ok',
|
||||
|
@ -73,7 +76,7 @@ class zcfsUrlHandler extends dcUrlHandlers
|
|||
|
||||
# Server js
|
||||
} elseif ($args == '/zcfsupd.js' && 3 == $s->bhv_pub_upd) {
|
||||
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates');
|
||||
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), My::path() . '/default-templates');
|
||||
self::serveDocument(
|
||||
'zcfsupd.js',
|
||||
'text/javascript',
|
||||
|
@ -83,8 +86,12 @@ class zcfsUrlHandler extends dcUrlHandlers
|
|||
|
||||
# Server feeds description page
|
||||
} elseif (in_array($args, ['', '/']) && $s->pub_active) {
|
||||
$tplset = dcCore::app()->themes->moduleInfo(dcCore::app()->blog->settings->system->theme, 'tplset');
|
||||
$path = __DIR__ . '/default-templates/';
|
||||
$theme = dcCore::app()->blog->settings->get('system')->get('theme');
|
||||
if (!is_string($theme)) {
|
||||
self::p404();
|
||||
}
|
||||
$tplset = dcCore::app()->themes->moduleInfo($theme, 'tplset');
|
||||
$path = My::path() . '/default-templates/';
|
||||
if (!empty($tplset) && is_dir($path . $tplset)) {
|
||||
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), $path . $tplset);
|
||||
} else {
|
||||
|
@ -96,7 +103,5 @@ class zcfsUrlHandler extends dcUrlHandlers
|
|||
else {
|
||||
self::p404();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
141
src/Widgets.php
141
src/Widgets.php
|
@ -10,38 +10,33 @@
|
|||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
declare(strict_types=1);
|
||||
|
||||
dcCore::app()->addBehavior(
|
||||
'initWidgets',
|
||||
['zoneclearFeedServerWidget', 'adminSource']
|
||||
);
|
||||
dcCore::app()->addBehavior(
|
||||
'initWidgets',
|
||||
['zoneclearFeedServerWidget', 'adminNumber']
|
||||
);
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use dcCore;
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Dotclear\Plugin\widgets\WidgetsStack;
|
||||
use Dotclear\Plugin\widgets\WidgetsElement;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Mix your blog with a feeds planet - widgets methods.
|
||||
* @since 2.6
|
||||
* Widgets.
|
||||
*
|
||||
* A widget to list feeds source.
|
||||
* A widget to list feeds statistics.
|
||||
*/
|
||||
class zoneclearFeedServerWidget
|
||||
class Widgets
|
||||
{
|
||||
/**
|
||||
* Widget configuration for sources list.
|
||||
*
|
||||
* @param dcWidgets $w dcWidgets instance
|
||||
* @param WidgetsStack $w WidgetsStack instance
|
||||
*/
|
||||
public static function adminSource($w)
|
||||
public static function init(WidgetsStack $w): void
|
||||
{
|
||||
$w
|
||||
->create(
|
||||
'zcfssource',
|
||||
__('Feeds server: sources'),
|
||||
['zoneclearFeedServerWidget', 'publicSource'],
|
||||
[self::class, 'publicSource'],
|
||||
null,
|
||||
__('List sources of feeds')
|
||||
)
|
||||
|
@ -85,20 +80,12 @@ class zoneclearFeedServerWidget
|
|||
->addContentOnly()
|
||||
->addClass()
|
||||
->addOffline();
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget configuration for feeds info.
|
||||
*
|
||||
* @param dcWidgets $w dcWidgets instance
|
||||
*/
|
||||
public static function adminNumber($w)
|
||||
{
|
||||
$w
|
||||
->create(
|
||||
'zcfsnumber',
|
||||
__('Feeds server: numbers'),
|
||||
['zoneclearFeedServerWidget', 'publicNumber'],
|
||||
[self::class, 'publicNumber'],
|
||||
null,
|
||||
__('Show some numbers about feeds')
|
||||
)
|
||||
|
@ -144,59 +131,58 @@ class zoneclearFeedServerWidget
|
|||
/**
|
||||
* Widget for sources list.
|
||||
*
|
||||
* @param dcWidget $w dcWidget instance
|
||||
* @param WidgetsElement $w Widgets Element instance
|
||||
*/
|
||||
public static function publicSource($w)
|
||||
public static function publicSource(WidgetsElement $w): string
|
||||
{
|
||||
if ($w->offline) {
|
||||
return null;
|
||||
}
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
|
||||
if (!dcCore::app()->blog->settings->__get(basename(__DIR__))->active
|
||||
if ($w->__get('offline')
|
||||
|| !$s->active
|
||||
|| !$w->checkHomeOnly(dcCore::app()->url->type)
|
||||
) {
|
||||
return null;
|
||||
return '';
|
||||
}
|
||||
|
||||
$p = [];
|
||||
$p['order'] = ($w->sortby && in_array($w->sortby, ['feed_upd_last', 'lowername', 'feed_creadt'])) ?
|
||||
$w->sortby . ' ' : 'feed_upd_last ';
|
||||
$p['order'] .= $w->sort == 'desc' ? 'DESC' : 'ASC';
|
||||
$p['limit'] = abs((int) $w->limit);
|
||||
$p['order'] = ($w->__get('sortby') && in_array($w->__get('sortby'), ['feed_upd_last', 'lowername', 'feed_creadt'])) ?
|
||||
$w->__get('sortby') . ' ' : 'feed_upd_last ';
|
||||
$p['order'] .= $w->__get('sort') == 'desc' ? 'DESC' : 'ASC';
|
||||
$p['limit'] = is_numeric($w->__get('limit')) ? abs((int) $w->__get('limit')) : 10;
|
||||
$p['feed_status'] = 1;
|
||||
|
||||
$zc = new zoneclearFeedServer();
|
||||
$rs = $zc->getFeeds($p);
|
||||
|
||||
$rs = $z->getFeeds($p);
|
||||
if ($rs->isEmpty()) {
|
||||
return null;
|
||||
return '';
|
||||
}
|
||||
|
||||
$lines = [];
|
||||
$i = 1;
|
||||
while ($rs->fetch()) {
|
||||
$row = new FeedRow($rs);
|
||||
$lines[] = sprintf(
|
||||
'<li><a href="%s" title="%s">%s</a></li>',
|
||||
$rs->feed_url,
|
||||
$rs->feed_owner,
|
||||
$rs->feed_name
|
||||
$row->url,
|
||||
$row->owner,
|
||||
$row->name
|
||||
);
|
||||
$i++;
|
||||
}
|
||||
$pub = '';
|
||||
if ($w->pagelink && dcCore::app()->blog->settings->__get(basename(__DIR__))->pub_active) {
|
||||
if ($w->__get('pagelink') && $s->pub_active) {
|
||||
$pub = sprintf(
|
||||
'<p><strong><a href="%s">%s</a></strong></p>',
|
||||
dcCore::app()->blog->url . dcCore::app()->url->getBase('zoneclearFeedsPage'),
|
||||
html::escapeHTML($w->pagelink)
|
||||
dcCore::app()->blog?->url . dcCore::app()->url->getBase('zoneclearFeedsPage'),
|
||||
Html::escapeHTML(is_string($w->__get('pagelink')) ? $w->__get('pagelink') : '')
|
||||
);
|
||||
}
|
||||
|
||||
return $w->renderDiv(
|
||||
$w->content_only,
|
||||
'zoneclear-sources ' . $w->class,
|
||||
(bool) $w->__get('content_only'),
|
||||
'zoneclear-sources ' . $w->__get('class'),
|
||||
'',
|
||||
($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') .
|
||||
($w->__get('title') ? $w->renderTitle(Html::escapeHTML(is_string($w->__get('title')) ? $w->__get('title') : '')) : '') .
|
||||
sprintf('<ul>%s</ul>', implode('', $lines)) . $pub
|
||||
);
|
||||
}
|
||||
|
@ -204,38 +190,38 @@ class zoneclearFeedServerWidget
|
|||
/**
|
||||
* Widget for feeds info.
|
||||
*
|
||||
* @param dcWidget $w dcWidget instance
|
||||
* @param WidgetsElement $w Widgets Element instance
|
||||
*/
|
||||
public static function publicNumber($w)
|
||||
public static function publicNumber(WidgetsElement $w): string
|
||||
{
|
||||
if ($w->offline) {
|
||||
return;
|
||||
}
|
||||
$z = ZoneclearFeedServer::instance();
|
||||
$s = $z->settings;
|
||||
|
||||
if (!dcCore::app()->blog->settings->__get(basename(__DIR__))->active
|
||||
if ($w->__get('offline')
|
||||
|| !$s->active
|
||||
|| !$w->checkHomeOnly(dcCore::app()->url->type)
|
||||
) {
|
||||
return null;
|
||||
return '';
|
||||
}
|
||||
|
||||
$zc = new zoneclearFeedServer();
|
||||
$content = '';
|
||||
|
||||
# Feed
|
||||
if ($w->feed_show) {
|
||||
$title = ($w->feed_title ? sprintf(
|
||||
if ($w->__get('feed_show')) {
|
||||
$title = ($w->__get('feed_title') ? sprintf(
|
||||
'<strong>%s</strong> ',
|
||||
html::escapeHTML($w->feed_title)
|
||||
Html::escapeHTML(is_string($w->__get('feed_title')) ? $w->__get('feed_title') : '')
|
||||
) : '');
|
||||
|
||||
$count = $zc->getFeeds([], true)->f(0);
|
||||
$count = $z->getFeeds([], true)->f(0);
|
||||
$count = is_numeric($count) ? (int) $count : 0;
|
||||
|
||||
$text = $count ? sprintf(__('one source', '%d sources', $count), $count) : __('no sources');
|
||||
|
||||
if (dcCore::app()->blog->settings->__get(basename(__DIR__))->pub_active) {
|
||||
if ($s->pub_active) {
|
||||
$text = sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
dcCore::app()->blog->url . dcCore::app()->url->getBase('zoneclearFeedsPage'),
|
||||
dcCore::app()->blog?->url . dcCore::app()->url->getBase('zoneclearFeedsPage'),
|
||||
$text
|
||||
);
|
||||
}
|
||||
|
@ -244,18 +230,21 @@ class zoneclearFeedServerWidget
|
|||
}
|
||||
|
||||
# Entry
|
||||
if ($w->entry_show) {
|
||||
if ($w->__get('entry_show')) {
|
||||
$count = 0;
|
||||
$feeds = $zc->getFeeds();
|
||||
$feeds = $z->getFeeds();
|
||||
|
||||
if (!$feeds->isEmpty()) {
|
||||
while ($feeds->fetch()) {
|
||||
$count += (int) $zc->getPostsByFeed(['feed_id' => $feeds->feed_id], true)->f(0);
|
||||
$fid = is_numeric($feeds->f('feed_id')) ? (int) $feeds->f('feed_id') : 0;
|
||||
$c = $z->getPostsByFeed(['feed_id' => $fid], true)->f(0);
|
||||
$c = is_numeric($c) ? (int) $c : 0;
|
||||
$count += $c;
|
||||
}
|
||||
}
|
||||
$title = ($w->entry_title ? sprintf(
|
||||
$title = ($w->__get('entry_title') ? sprintf(
|
||||
'<strong>%s</strong> ',
|
||||
html::escapeHTML($w->entry_title)
|
||||
Html::escapeHTML(is_string($w->__get('entry_title')) ? $w->__get('entry_title') : '')
|
||||
) : '');
|
||||
|
||||
$text = $count ? sprintf(__('one entry', '%d entries', $count), $count) : __('no entries');
|
||||
|
@ -264,15 +253,15 @@ class zoneclearFeedServerWidget
|
|||
}
|
||||
|
||||
if (!$content) {
|
||||
return null;
|
||||
return '';
|
||||
}
|
||||
|
||||
# Display
|
||||
return $w->renderDiv(
|
||||
$w->content_only,
|
||||
'zoneclear-number ' . $w->class,
|
||||
(bool) $w->__get('content_only'),
|
||||
'zoneclear-number ' . $w->__get('class'),
|
||||
'',
|
||||
($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') .
|
||||
($w->__get('title') ? $w->renderTitle(Html::escapeHTML(is_string($w->__get('title')) ? $w->__get('title') : '')) : '') .
|
||||
sprintf('<ul>%s</ul>', $content)
|
||||
);
|
||||
}
|
||||
|
|
976
src/ZoneclearFeedServer.php
Normal file
976
src/ZoneclearFeedServer.php
Normal file
|
@ -0,0 +1,976 @@
|
|||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dotclear\Plugin\zoneclearFeedServer;
|
||||
|
||||
use ArrayObject;
|
||||
use dcAuth;
|
||||
use dcBlog;
|
||||
use dcCategories;
|
||||
use dcCore;
|
||||
use dcMeta;
|
||||
use dcUtils;
|
||||
use Dotclear\Database\{
|
||||
Cursor,
|
||||
MetaRecord
|
||||
};
|
||||
use Dotclear\Database\Statement\{
|
||||
DeleteStatement,
|
||||
JoinStatement,
|
||||
SelectStatement
|
||||
};
|
||||
use Dotclear\Helper\Date;
|
||||
use Dotclear\Helper\File\{
|
||||
Files,
|
||||
Path
|
||||
};
|
||||
use Dotclear\Helper\Html\Html;
|
||||
use Dotclear\Helper\Network\Feed\{
|
||||
Parser,
|
||||
Reader
|
||||
};
|
||||
use Dotclear\Helper\Text;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Main module class.
|
||||
*/
|
||||
class ZoneclearFeedServer
|
||||
{
|
||||
/** @var int Net HTTP feed reader timeout */
|
||||
public const NET_HTTP_TIMEOUT = 5;
|
||||
|
||||
/** @var string Net HTTP feed reader agent */
|
||||
public const NET_HTTP_AGENT = 'zoneclearFeedServer - http://zoneclear.org';
|
||||
|
||||
/** @var int Net HTTP feed reader max redirect */
|
||||
public const NET_HTTP_MAX_REDIRECT = 2;
|
||||
|
||||
/** @var ZoneclearFeedServer Self instance */
|
||||
private static $instance;
|
||||
|
||||
/** @var Settings The settings instance */
|
||||
public readonly Settings $settings;
|
||||
|
||||
/** @var null|resource $lock File lock for update */
|
||||
private static $lock = null;
|
||||
|
||||
/** @var null|string $user Affiliate user ID */
|
||||
private $user = null;
|
||||
|
||||
/**
|
||||
* Constructor load settings.
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
$this->settings = Settings::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class instance.
|
||||
*
|
||||
* @return ZoneclearFeedServer Self instacne
|
||||
*/
|
||||
public static function instance(): ZoneclearFeedServer
|
||||
{
|
||||
if (!(self::$instance instanceof ZoneclearFeedServer)) {
|
||||
self::$instance = new ZoneclearFeedServer();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open database table cursor.
|
||||
*
|
||||
* @return Cursor The cursor
|
||||
*/
|
||||
public function openCursor(): Cursor
|
||||
{
|
||||
return dcCore::app()->con->openCursor(dcCore::app()->prefix . My::TABLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update feed record.
|
||||
*
|
||||
* @param int $id The feed ID
|
||||
* @param Cursor $cur The cursor instance
|
||||
*/
|
||||
public function updateFeed(int $id, Cursor $cur): void
|
||||
{
|
||||
dcCore::app()->con->writeLock(dcCore::app()->prefix . My::TABLE_NAME);
|
||||
|
||||
try {
|
||||
if ($id < 1) {
|
||||
throw new Exception(__('No such ID'));
|
||||
}
|
||||
|
||||
$cur->setField('feed_upddt', date('Y-m-d H:i:s'));
|
||||
|
||||
$cur->update(sprintf(
|
||||
"WHERE feed_id = %s AND blog_id = '%s' ",
|
||||
$id,
|
||||
dcCore::app()->con->escapeStr((string) dcCore::app()->blog?->id)
|
||||
));
|
||||
dcCore::app()->con->unlock();
|
||||
$this->trigger();
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->con->unlock();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterUpdateFeed -- Cursor, int
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAfterUpdateFeed', $cur, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add feed record.
|
||||
*
|
||||
* @param Cursor $cur The cursor
|
||||
*
|
||||
* @return int The new feed ID
|
||||
*/
|
||||
public function addFeed(Cursor $cur): int
|
||||
{
|
||||
dcCore::app()->con->writeLock(dcCore::app()->prefix . My::TABLE_NAME);
|
||||
|
||||
try {
|
||||
$cur->setField('feed_id', $this->getNextId());
|
||||
$cur->setField('blog_id', dcCore::app()->con->escapeStr((string) dcCore::app()->blog?->id));
|
||||
$cur->setField('feed_creadt', date('Y-m-d H:i:s'));
|
||||
$cur->setField('feed_upddt', date('Y-m-d H:i:s'));
|
||||
|
||||
//add getFeedCursor here
|
||||
|
||||
$cur->insert();
|
||||
dcCore::app()->con->unlock();
|
||||
$this->trigger();
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->con->unlock();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$id = is_numeric($cur->getField('feed_id')) ? (int) $cur->getField('feed_id') : 0;
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterAddFeed -- Cursor, int
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAfterAddFeed', $cur, $id);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick enable / disable feed.
|
||||
*
|
||||
* @param int $id The feed ID
|
||||
* @param bool $enable Enable feed
|
||||
* @param int $time Force update time
|
||||
*/
|
||||
public function enableFeed(int $id, bool $enable = true, int $time = 0): void
|
||||
{
|
||||
try {
|
||||
if ($id < 1) {
|
||||
throw new Exception(__('No such ID'));
|
||||
}
|
||||
|
||||
$cur = $this->openCursor();
|
||||
dcCore::app()->con->writeLock(dcCore::app()->prefix . My::TABLE_NAME);
|
||||
|
||||
$cur->setField('feed_upddt', date('Y-m-d H:i:s'));
|
||||
$cur->setField('feed_status', (int) $enable);
|
||||
if (0 < $time) {
|
||||
$cur->setField('feed_upd_last', $time);
|
||||
}
|
||||
|
||||
$cur->update(sprintf(
|
||||
"WHERE feed_id = %s AND blog_id = '%s' ",
|
||||
$id,
|
||||
dcCore::app()->con->escapeStr((string) dcCore::app()->blog?->id)
|
||||
));
|
||||
dcCore::app()->con->unlock();
|
||||
$this->trigger();
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->con->unlock();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterEnableFeed -- int, bool, int
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAfterEnableFeed', $id, $enable, $time);
|
||||
}
|
||||
|
||||
#
|
||||
/**
|
||||
* Delete record (this not deletes post).
|
||||
*
|
||||
* @param int $id The feed ID
|
||||
*/
|
||||
public function deleteFeed(int $id): void
|
||||
{
|
||||
if ($id < 1) {
|
||||
throw new Exception(__('No such ID'));
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerBeforeDeleteFeed -- int
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerBeforeDeleteFeed', $id);
|
||||
|
||||
$sql = new DeleteStatement();
|
||||
$sql->from(dcCore::app()->prefix . My::TABLE_NAME)
|
||||
->where('feed_id ' . $sql->in($id))
|
||||
->and('blog_id = ' . $sql->quote((string) dcCore::app()->blog?->id))
|
||||
->delete();
|
||||
|
||||
$this->trigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all post(s) meta.
|
||||
*
|
||||
* This deletes all post(s) related meta,
|
||||
* the post from the planet become an ordinary post.
|
||||
*
|
||||
* @param null|int $id The post ID (or null for all!)
|
||||
*/
|
||||
public static function deletePostsMeta(?int $id): void
|
||||
{
|
||||
$sql = new DeleteStatement();
|
||||
$sql->from(dcCore::app()->prefix . dcMeta::META_TABLE_NAME)
|
||||
->where('meta_type ' . $sql->in([
|
||||
My::META_PREFIX . 'url',
|
||||
My::META_PREFIX . 'author',
|
||||
My::META_PREFIX . 'site',
|
||||
My::META_PREFIX . 'sitename',
|
||||
My::META_PREFIX . 'id',
|
||||
]));
|
||||
|
||||
if (!is_null($post_id)) {
|
||||
$sql->and('post_id = ' . $id);
|
||||
}
|
||||
|
||||
$sql->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get related posts.
|
||||
*
|
||||
* @param array<string,int|string|array> $params The query params
|
||||
* @param bool $count_only Return only result count
|
||||
*
|
||||
* @return MetaRecord The record instance
|
||||
*/
|
||||
public function getPostsByFeed(array $params = [], bool $count_only = false): MetaRecord
|
||||
{
|
||||
if (!isset($params['feed_id']) || !is_numeric($params['feed_id'])) {
|
||||
return MetaRecord::newFromArray([]);
|
||||
}
|
||||
|
||||
$sql = new SelectStatement();
|
||||
$sql->join(
|
||||
(new JoinStatement())
|
||||
->left()
|
||||
->from(dcCore::app()->prefix . dcMeta::META_TABLE_NAME . ' F')
|
||||
->on('P.post_id = F.post_id')
|
||||
->statement()
|
||||
);
|
||||
|
||||
$params['sql'] = "AND P.blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog?->id) . "' " .
|
||||
"AND F.meta_type = '" . My::META_PREFIX . "id' " .
|
||||
"AND F.meta_id = '" . dcCore::app()->con->escapeStr((string) $params['feed_id']) . "' ";
|
||||
|
||||
unset($params['feed_id']);
|
||||
|
||||
$rs = dcCore::app()->blog?->getPosts($params, $count_only, $sql);
|
||||
|
||||
return is_null($rs) ? MetaRecord::newFromArray([]) : $rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feed record.
|
||||
*
|
||||
* @param array<string,int|string|array> $params The query params
|
||||
* @param bool $count_only Return only result count
|
||||
*
|
||||
* @return MetaRecord The record instance
|
||||
*/
|
||||
public function getFeeds(array $params = [], bool $count_only = false): MetaRecord
|
||||
{
|
||||
if ($count_only) {
|
||||
$strReq = 'SELECT count(Z.feed_id) ';
|
||||
} else {
|
||||
$content_req = '';
|
||||
if (!empty($params['columns']) && is_array($params['columns'])) {
|
||||
$content_req .= implode(', ', $params['columns']) . ', ';
|
||||
}
|
||||
|
||||
$strReq = 'SELECT Z.feed_id, Z.feed_creadt, Z.feed_upddt, Z.feed_type, ' .
|
||||
'Z.blog_id, Z.cat_id, ' .
|
||||
'Z.feed_upd_int, Z.feed_upd_last, Z.feed_status, ' .
|
||||
$content_req .
|
||||
'LOWER(Z.feed_name) as lowername, Z.feed_name, Z.feed_desc, ' .
|
||||
'Z.feed_url, Z.feed_feed, Z.feed_get_tags, ' .
|
||||
'Z.feed_tags, Z.feed_owner, Z.feed_tweeter, Z.feed_lang, ' .
|
||||
'Z.feed_nb_out, Z.feed_nb_in, ' .
|
||||
'C.cat_title, C.cat_url, C.cat_desc ';
|
||||
}
|
||||
|
||||
$strReq .= 'FROM ' . dcCore::app()->prefix . My::TABLE_NAME . ' Z ' .
|
||||
'LEFT OUTER JOIN ' . dcCore::app()->prefix . dcCategories::CATEGORY_TABLE_NAME . ' C ON Z.cat_id = C.cat_id ';
|
||||
|
||||
if (!empty($params['from']) && is_string($params['from'])) {
|
||||
$strReq .= $params['from'] . ' ';
|
||||
}
|
||||
|
||||
$strReq .= "WHERE Z.blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog?->id) . "' ";
|
||||
|
||||
if (isset($params['feed_type']) && is_string($params['feed_type'])) {
|
||||
$strReq .= "AND Z.feed_type = '" . dcCore::app()->con->escapeStr((string) $params['feed_type']) . "' ";
|
||||
} else {
|
||||
$strReq .= "AND Z.feed_type = 'feed' ";
|
||||
}
|
||||
|
||||
if (!empty($params['feed_id'])) {
|
||||
if (is_array($params['feed_id'])) {
|
||||
array_walk($params['feed_id'], function (&$v, $k) { if ($v !== null) { $v = (int) $v; }});
|
||||
} elseif (is_numeric($params['feed_id'])) {
|
||||
$params['feed_id'] = [(int) $params['feed_id']];
|
||||
}
|
||||
$strReq .= 'AND Z.feed_id ' . dcCore::app()->con->in($params['feed_id']);
|
||||
}
|
||||
|
||||
if (isset($params['feed_feed']) && is_string($params['feed_feed'])) {
|
||||
$strReq .= "AND Z.feed_feed = '" . dcCore::app()->con->escapeStr((string) $params['feed_feed']) . "' ";
|
||||
}
|
||||
if (isset($params['feed_url']) && is_string($params['feed_url'])) {
|
||||
$strReq .= "AND Z.feed_url = '" . dcCore::app()->con->escapeStr((string) $params['feed_url']) . "' ";
|
||||
}
|
||||
if (isset($params['feed_status'])) {
|
||||
$strReq .= 'AND Z.feed_status = ' . ((int) $params['feed_status']) . ' ';
|
||||
}
|
||||
|
||||
if (!empty($params['q']) && is_string($params['q'])) {
|
||||
$q = dcCore::app()->con->escapeStr((string) str_replace('*', '%', strtolower($params['q'])));
|
||||
$strReq .= "AND LOWER(Z.feed_name) LIKE '" . $q . "' ";
|
||||
}
|
||||
|
||||
if (!empty($params['sql']) && is_string($params['sql'])) {
|
||||
$strReq .= $params['sql'] . ' ';
|
||||
}
|
||||
|
||||
if (!$count_only) {
|
||||
if (!empty($params['order']) && is_string($params['order'])) {
|
||||
$strReq .= 'ORDER BY ' . dcCore::app()->con->escapeStr((string) $params['order']) . ' ';
|
||||
} else {
|
||||
$strReq .= 'ORDER BY Z.feed_upddt DESC ';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$count_only && isset($params['limit'])) {
|
||||
if (is_numeric($params['limit'])) {
|
||||
$params['limit'] = (int) $params['limit'];
|
||||
}
|
||||
if (is_int($params['limit']) || is_array($params['limit'])) {
|
||||
$strReq .= dcCore::app()->con->limit($params['limit']);
|
||||
}
|
||||
}
|
||||
|
||||
return new MetaRecord(dcCore::app()->con->select($strReq));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next table id.
|
||||
*
|
||||
* @return int THe next ID
|
||||
*/
|
||||
private function getNextId(): int
|
||||
{
|
||||
$sql = new SelectStatement();
|
||||
$rs = $sql
|
||||
->column($sql->max('feed_id'))
|
||||
->from(dcCore::app()->prefix . My::TABLE_NAME)
|
||||
->select();
|
||||
|
||||
return (int) $rs?->f(0) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock a file to see if an update is ongoing.
|
||||
*
|
||||
* @return bool True if file is locked
|
||||
*/
|
||||
public function lockUpdate()
|
||||
{
|
||||
try {
|
||||
# Need flock function
|
||||
if (!function_exists('flock')) {
|
||||
throw new Exception("Can't call php function named flock");
|
||||
}
|
||||
# Cache writable ?
|
||||
if (!is_writable(DC_TPL_CACHE)) {
|
||||
throw new Exception("Can't write in cache fodler");
|
||||
}
|
||||
# Set file path
|
||||
$f_md5 = md5((string) dcCore::app()->blog?->id);
|
||||
$cached_file = sprintf(
|
||||
'%s/%s/%s/%s/%s.txt',
|
||||
DC_TPL_CACHE,
|
||||
'periodical',
|
||||
substr($f_md5, 0, 2),
|
||||
substr($f_md5, 2, 2),
|
||||
$f_md5
|
||||
);
|
||||
# Real path
|
||||
$cached_file = Path::real($cached_file, false);
|
||||
if (false === $cached_file) {
|
||||
throw new Exception("Can't get cache file path");
|
||||
}
|
||||
# Make dir
|
||||
if (!is_dir(dirname($cached_file))) {
|
||||
Files::makeDir(dirname($cached_file), true);
|
||||
}
|
||||
# Make file
|
||||
if (!file_exists($cached_file)) {
|
||||
!$fp = @fopen($cached_file, 'w');
|
||||
if ($fp === false) {
|
||||
throw new Exception("Can't create file");
|
||||
}
|
||||
fwrite($fp, '1', strlen('1'));
|
||||
fclose($fp);
|
||||
}
|
||||
# Open file
|
||||
if (!($fp = @fopen($cached_file, 'r+'))) {
|
||||
throw new Exception("Can't open file");
|
||||
}
|
||||
# Lock file
|
||||
if (!flock($fp, LOCK_EX)) {
|
||||
throw new Exception("Can't lock file");
|
||||
}
|
||||
self::$lock = $fp;
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock file of update process.
|
||||
*/
|
||||
public function unlockUpdate(): void
|
||||
{
|
||||
if (!is_null(self::$lock)) {
|
||||
@fclose(self::$lock);
|
||||
self::$lock = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and add/update post related to record if needed.
|
||||
*
|
||||
* @param int $id The feed ID
|
||||
* @param bool $throw Throw exception or end silently
|
||||
*
|
||||
* @return bool True on success
|
||||
*/
|
||||
public function checkFeedsUpdate(int $id = 0, bool $throw = false): bool
|
||||
{
|
||||
$s = $this->settings;
|
||||
|
||||
# Not configured
|
||||
if (is_null(dcCore::app()->auth) || !$s->active || !$s->user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# Limit to one update at a time
|
||||
try {
|
||||
$this->lockUpdate();
|
||||
} catch (Exception $e) {
|
||||
if ($throw) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$tz = dcCore::app()->blog?->settings->get('system')->get('blog_timezone');
|
||||
Date::setTZ(is_string($tz) ? $tz : 'UTC');
|
||||
$time = time();
|
||||
|
||||
# All feeds or only one (from admin)
|
||||
$f = !$id ?
|
||||
$this->getFeeds(['feed_status' => 1, 'order' => 'feed_upd_last ASC']) :
|
||||
$this->getFeeds(['feed_id' => $id]);
|
||||
|
||||
# No feed
|
||||
if ($f->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$enabled = false;
|
||||
$updates = false;
|
||||
$loop_mem = [];
|
||||
|
||||
$i = 0;
|
||||
|
||||
$cur_post = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcBlog::POST_TABLE_NAME);
|
||||
$cur_meta = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcMeta::META_TABLE_NAME);
|
||||
|
||||
while ($f->fetch()) {
|
||||
$row = new FeedRow($f);
|
||||
# Check if feed need update
|
||||
if ($id
|
||||
|| $i < $s->update_limit && $row->status == 1 && ($time > $row->upd_last + $row->upd_int)
|
||||
) {
|
||||
if (!$enabled) {
|
||||
# Set feeds user
|
||||
$this->enableUser(true);
|
||||
$enabled = true;
|
||||
}
|
||||
$i++;
|
||||
$feed = self::readFeed($row->feed);
|
||||
|
||||
# Nothing to parse
|
||||
if (!$feed) {
|
||||
# Keep active empty feed or disable it ?
|
||||
if (!$s->keep_empty_feed) {
|
||||
$this->enableFeed($row->id, false);
|
||||
} else {
|
||||
# Set update time of this feed
|
||||
$this->enableFeed($row->id, true, $time);
|
||||
}
|
||||
$i++;
|
||||
|
||||
# Not updated since last visit
|
||||
} elseif (!$id
|
||||
&& '' != $feed->pubdate
|
||||
&& strtotime($feed->pubdate) < $row->upd_last
|
||||
) {
|
||||
# Set update time of this feed
|
||||
$this->enableFeed($row->id, true, $time);
|
||||
$i++;
|
||||
} else {
|
||||
# Set update time of this feed
|
||||
$this->enableFeed($row->id, (bool) $row->status, $time);
|
||||
|
||||
dcCore::app()->con->begin();
|
||||
|
||||
foreach ($feed->items as $item) {
|
||||
$item_TS = $item->TS ? $item->TS : $time;
|
||||
|
||||
// I found that mercurial atom feed did not repect standard
|
||||
$item_link = @$item->link;
|
||||
if (!$item_link) {
|
||||
$item_link = @$item->guid;
|
||||
}
|
||||
# Unknow feed item link
|
||||
if (!$item_link) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item_link = dcCore::app()->con->escapeStr((string) $item_link);
|
||||
$is_new_published_entry = false;
|
||||
|
||||
# Not updated since last visit
|
||||
if (!$id && $item_TS < $row->upd_last) {
|
||||
continue;
|
||||
}
|
||||
|
||||
# Fix loop twin
|
||||
if (in_array($item_link, $loop_mem)) {
|
||||
continue;
|
||||
}
|
||||
$loop_mem[] = $item_link;
|
||||
|
||||
# Check if entry exists
|
||||
$sql = new SelectStatement();
|
||||
$old_post = $sql
|
||||
->columns([
|
||||
'P.post_id',
|
||||
'P.post_status',
|
||||
])
|
||||
->from($sql->as(dcCore::app()->prefix . dcBlog::POST_TABLE_NAME, 'P'))
|
||||
->join(
|
||||
(new JoinStatement())
|
||||
->inner()
|
||||
->from($sql->as(dcCore::app()->prefix . dcMeta::META_TABLE_NAME, 'M'))
|
||||
->on('P.post_id = M.post_id')
|
||||
->statement()
|
||||
)
|
||||
->where('blog_id = ' . $sql->quote((string) dcCore::app()->blog?->id))
|
||||
->and("meta_type = '" . My::META_PREFIX . "url'")
|
||||
->and('meta_id = ' . $sql->quote($item_link))
|
||||
->select();
|
||||
|
||||
if (is_null($old_post)) {
|
||||
$old_post = MetaRecord::newFromArray([]);
|
||||
}
|
||||
|
||||
# Prepare entry Cursor
|
||||
$cur_post->clean();
|
||||
$cur_post->setField('post_dt', date('Y-m-d H:i:s', $item_TS));
|
||||
if ($row->cat_id) {
|
||||
$cur_post->setField('cat_id', $row->cat_id);
|
||||
}
|
||||
$post_content = $item->content ? $item->content : $item->description;
|
||||
$cur_post->setField('post_format', 'xhtml');
|
||||
$cur_post->setField('post_content', Html::absoluteURLs($post_content, $feed->link));
|
||||
$cur_post->setField('post_title', $item->title ? $item->title : Text::cutString(Html::clean(is_string($cur_post->getField('post_content')) ? $cur_post->getField('post_content') : ''), 60));
|
||||
$creator = $item->creator ? $item->creator : $row->owner;
|
||||
|
||||
try {
|
||||
# Create entry
|
||||
if ($old_post->isEmpty()) {
|
||||
# Post
|
||||
$cur_post->setField('user_id', dcCore::app()->auth->userID());
|
||||
$cur_post->setField('post_format', 'xhtml');
|
||||
$cur_post->setField('post_status', $s->post_status_new);
|
||||
$cur_post->setField('post_open_comment', 0);
|
||||
$cur_post->setField('post_open_tb', 0);
|
||||
|
||||
$post_id = dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->blog, 'addPost'],
|
||||
$cur_post
|
||||
);
|
||||
|
||||
# Auto tweet new post
|
||||
if (!empty($cur_post->getField('post_status'))) {
|
||||
$is_new_published_entry = true;
|
||||
}
|
||||
|
||||
# Update entry
|
||||
} else {
|
||||
$post_id = is_numeric($old_post->f('post_id')) ? (int) $old_post->f('post_id') : 0;
|
||||
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->blog, 'updPost'],
|
||||
$post_id,
|
||||
$cur_post
|
||||
);
|
||||
|
||||
# Quick delete old meta
|
||||
$sql = new DeleteStatement();
|
||||
$sql->from(dcCore::app()->prefix . dcMeta::META_TABLE_NAME)
|
||||
->where('post_id = ' . $post_id)
|
||||
->and($sql->like('meta_type', My::META_PREFIX . '%'))
|
||||
->delete();
|
||||
|
||||
# Delete old tags
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->meta, 'delPostMeta'],
|
||||
$post_id,
|
||||
'tag'
|
||||
);
|
||||
}
|
||||
|
||||
# Quick add new meta
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->setField('post_id', $post_id);
|
||||
$cur_meta->setField('meta_type', My::META_PREFIX . 'url');
|
||||
$cur_meta->setField('meta_id', $item_link);
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->setField('post_id', $post_id);
|
||||
$cur_meta->setField('meta_type', My::META_PREFIX . 'author');
|
||||
$cur_meta->setField('meta_id', $creator);
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->setField('post_id', $post_id);
|
||||
$cur_meta->setField('meta_type', My::META_PREFIX . 'site');
|
||||
$cur_meta->setField('meta_id', $row->url);
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->setField('post_id', $post_id);
|
||||
$cur_meta->setField('meta_type', My::META_PREFIX . 'sitename');
|
||||
$cur_meta->setField('meta_id', $row->name);
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->setField('post_id', $post_id);
|
||||
$cur_meta->setField('meta_type', My::META_PREFIX . 'id');
|
||||
$cur_meta->setField('meta_id', $row->id);
|
||||
$cur_meta->insert();
|
||||
|
||||
# Add new tags
|
||||
$tags = dcCore::app()->meta->splitMetaValues($row->tags);
|
||||
if ($row->get_tags) {
|
||||
# Some feed subjects contains more than one tag
|
||||
foreach ($item->subject as $subjects) {
|
||||
$tmp = dcCore::app()->meta->splitMetaValues($subjects);
|
||||
$tags = array_merge($tags, $tmp);
|
||||
}
|
||||
$tags = array_unique($tags);
|
||||
}
|
||||
$formated_tags = [];
|
||||
foreach ($tags as $tag) {
|
||||
# Change tags case
|
||||
switch ((int) $s->tag_case) {
|
||||
case 3: $tag = strtoupper($tag);
|
||||
|
||||
break;
|
||||
case 2: $tag = strtolower($tag);
|
||||
|
||||
break;
|
||||
case 1: $tag = ucfirst(strtolower($tag));
|
||||
|
||||
break;
|
||||
default: /* do nothing */ break;
|
||||
}
|
||||
if (!in_array($tag, $formated_tags)) {
|
||||
$formated_tags[] = $tag;
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->meta, 'delPostMeta'],
|
||||
$post_id,
|
||||
'tag',
|
||||
dcMeta::sanitizeMetaID($tag)
|
||||
);
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->meta, 'setPostMeta'],
|
||||
$post_id,
|
||||
'tag',
|
||||
dcMeta::sanitizeMetaID($tag)
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->con->rollback();
|
||||
$this->enableUser(false);
|
||||
$this->unlockUpdate();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterCheckFeedUpdate -- FeedRow
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAfterCheckFeedUpdate', $row);
|
||||
}
|
||||
dcCore::app()->con->commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($enabled) {
|
||||
$this->enableUser(false);
|
||||
}
|
||||
$this->unlockUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permission to update post table.
|
||||
*
|
||||
* @param boolean $enable Enable or disable perm
|
||||
*/
|
||||
public function enableUser(bool $enable = false): void
|
||||
{
|
||||
if (is_null(dcCore::app()->auth)) {
|
||||
return;
|
||||
}
|
||||
|
||||
# Enable
|
||||
if ($enable) {
|
||||
// backup current user
|
||||
if (!is_null(dcCore::app()->auth->userID()) && !is_string(dcCore::app()->auth->userID())) {
|
||||
throw new Exception('Unable to backup user');
|
||||
}
|
||||
$this->user = dcCore::app()->auth->userID();
|
||||
// set zcfs posts user
|
||||
if (!dcCore::app()->auth->checkUser($this->settings->user)) {
|
||||
throw new Exception('Unable to set user');
|
||||
}
|
||||
# Disable
|
||||
} else {
|
||||
dcCore::app()->auth = null;
|
||||
dcCore::app()->auth = new dcAuth();
|
||||
// restore current user
|
||||
dcCore::app()->auth->checkUser($this->user ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and parse external feeds.
|
||||
*
|
||||
* @param string $url The feed URL
|
||||
*
|
||||
* @return Parser|false The parsed feed
|
||||
*/
|
||||
public static function readFeed(string $url): false|Parser
|
||||
{
|
||||
try {
|
||||
$feed_reader = new Reader();
|
||||
$feed_reader->setCacheDir(DC_TPL_CACHE);
|
||||
$feed_reader->setTimeout(self::NET_HTTP_TIMEOUT);
|
||||
$feed_reader->setMaxRedirects(self::NET_HTTP_MAX_REDIRECT);
|
||||
$feed_reader->setUserAgent(self::NET_HTTP_AGENT);
|
||||
|
||||
return $feed_reader->parse($url);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger blog.
|
||||
*/
|
||||
private function trigger(): void
|
||||
{
|
||||
dcCore::app()->blog?->triggerBlog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an URL is well formed.
|
||||
*
|
||||
* @param string $url The URL
|
||||
*
|
||||
* @return bool True if URL is allowed
|
||||
*/
|
||||
public static function validateURL(string $url): bool
|
||||
{
|
||||
return false !== strpos($url, 'http://')
|
||||
|| false !== strpos($url, 'https://');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full URL.
|
||||
*
|
||||
* Know bugs: anchor is not well parsed.
|
||||
*
|
||||
* @param string $root The root URL
|
||||
* @param string $url A URL
|
||||
*
|
||||
* @return string The parse URL
|
||||
*/
|
||||
public static function absoluteURL(string $root, string $url): string
|
||||
{
|
||||
$host = preg_replace(
|
||||
'|^([a-z]{3,}://)(.*?)/(.*)$|',
|
||||
'$1$2',
|
||||
$root
|
||||
);
|
||||
|
||||
$parse = parse_url($url);
|
||||
|
||||
if (empty($parse['scheme'])) {
|
||||
if (strpos($url, '/') === 0) {
|
||||
$url = $host . $url;
|
||||
} elseif (strpos($url, '#') === 0) {
|
||||
$url = $root . $url;
|
||||
} elseif (preg_match('|/$|', $root)) {
|
||||
$url = $root . $url;
|
||||
} else {
|
||||
$url = dirname($root) . '/' . $url;
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of (super)admins of current blog.
|
||||
*
|
||||
* @return array<string,string> List of UserCNs/UserIds
|
||||
*/
|
||||
public function getAllBlogAdmins(): array
|
||||
{
|
||||
$admins = [];
|
||||
|
||||
# Get super admins
|
||||
$sql = new SelectStatement();
|
||||
$rs = $sql
|
||||
->from(dcCore::app()->prefix . dcAuth::USER_TABLE_NAME)
|
||||
->columns([
|
||||
'user_id',
|
||||
'user_super',
|
||||
'user_name',
|
||||
'user_firstname',
|
||||
'user_displayname',
|
||||
])
|
||||
->where('user_super = 1')
|
||||
->and('user_status = 1')
|
||||
->select();
|
||||
|
||||
if (!is_null($rs) && !$rs->isEmpty()) {
|
||||
while ($rs->fetch()) {
|
||||
$user_cn = dcUtils::getUserCN(
|
||||
$rs->f('user_id'),
|
||||
$rs->f('user_name'),
|
||||
$rs->f('user_firstname'),
|
||||
$rs->f('user_displayname')
|
||||
);
|
||||
$admins[$user_cn . ' (super admin)'] = $rs->f('user_id');
|
||||
}
|
||||
}
|
||||
|
||||
# Get admins
|
||||
$sql = new SelectStatement();
|
||||
$rs = $sql
|
||||
->columns([
|
||||
'U.user_id',
|
||||
'U.user_super',
|
||||
'U.user_name',
|
||||
'U.user_firstname',
|
||||
'U.user_displayname',
|
||||
])
|
||||
->from($sql->as(dcCore::app()->prefix . dcAuth::USER_TABLE_NAME, 'U'))
|
||||
->join(
|
||||
(new JoinStatement())
|
||||
->left()
|
||||
->from($sql->as(dcCore::app()->prefix . dcAuth::PERMISSIONS_TABLE_NAME, 'P'))
|
||||
->on('U.user_id = P.user_id')
|
||||
->statement()
|
||||
)
|
||||
->where('U.user_status = 1')
|
||||
->and('P.blog_id = ' . $sql->quote((string) dcCore::app()->blog?->id))
|
||||
->and($sql->like('P.permissions', '%|admin|%'))
|
||||
->select();
|
||||
|
||||
if (!is_null($rs) && !$rs->isEmpty()) {
|
||||
while ($rs->fetch()) {
|
||||
$user_cn = dcUtils::getUserCN(
|
||||
$rs->f('user_id'),
|
||||
$rs->f('user_name'),
|
||||
$rs->f('user_firstname'),
|
||||
$rs->f('user_displayname')
|
||||
);
|
||||
$admins[$user_cn . ' (admin)'] = $rs->f('user_id');
|
||||
}
|
||||
}
|
||||
|
||||
return $admins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of urls where entries could be hacked.
|
||||
*
|
||||
* @return array<string,string> List of names/types of URLs
|
||||
*/
|
||||
public static function getPublicUrlTypes(): array
|
||||
{
|
||||
$types = new ArrayObject([
|
||||
__('Home page') => 'default',
|
||||
__('Entries pages') => 'post',
|
||||
__('Tags pages') => 'tag',
|
||||
__('Archives pages') => 'archive',
|
||||
__('Category pages') => 'category',
|
||||
__('Entries feed') => 'feed',
|
||||
]);
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerPublicUrlTypes -- ArrayObject
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerPublicUrlTypes', $types);
|
||||
|
||||
return $types->getArrayCopy();
|
||||
}
|
||||
}
|
|
@ -1,925 +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_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER
|
||||
* @brief Feeds server - main methods
|
||||
* @since 2.6
|
||||
*/
|
||||
class zoneclearFeedServer
|
||||
{
|
||||
public static $nethttp_timeout = 5;
|
||||
public static $nethttp_agent = 'zoneclearFeedServer - http://zoneclear.org';
|
||||
public static $nethttp_maxredirect = 2;
|
||||
|
||||
public $con;
|
||||
private $blog;
|
||||
private $table;
|
||||
private $lock = null;
|
||||
private $user = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->con = dcCore::app()->con;
|
||||
$this->blog = dcCore::app()->con->escape(dcCore::app()->blog->id);
|
||||
$this->table = dcCore::app()->prefix . initZoneclearFeedServer::TABLE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Short openCursor.
|
||||
*
|
||||
* @return cursor cursor instance
|
||||
*/
|
||||
public function openCursor()
|
||||
{
|
||||
return $this->con->openCursor($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update feed record.
|
||||
*
|
||||
* @param integer $id Feed id
|
||||
* @param cursor $cur cursor instance
|
||||
*/
|
||||
public function updFeed($id, cursor $cur)
|
||||
{
|
||||
$this->con->writeLock($this->table);
|
||||
|
||||
try {
|
||||
$id = (int) $id;
|
||||
|
||||
if ($id < 1) {
|
||||
throw new Exception(__('No such ID'));
|
||||
}
|
||||
|
||||
$cur->feed_upddt = date('Y-m-d H:i:s');
|
||||
|
||||
$cur->update(sprintf(
|
||||
"WHERE feed_id = %s AND blog_id = '%s' ",
|
||||
$id,
|
||||
$this->blog
|
||||
));
|
||||
$this->con->unlock();
|
||||
$this->trigger();
|
||||
} catch (Exception $e) {
|
||||
$this->con->unlock();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterUpdFeed
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAfterUpdFeed', $cur, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add feed record.
|
||||
*
|
||||
* @param cursor $cur cursor instance
|
||||
*/
|
||||
public function addFeed(cursor $cur)
|
||||
{
|
||||
$this->con->writeLock($this->table);
|
||||
|
||||
try {
|
||||
$cur->feed_id = $this->getNextId();
|
||||
$cur->blog_id = $this->blog;
|
||||
$cur->feed_creadt = date('Y-m-d H:i:s');
|
||||
$cur->feed_upddt = date('Y-m-d H:i:s');
|
||||
|
||||
//add getFeedCursor here
|
||||
|
||||
$cur->insert();
|
||||
$this->con->unlock();
|
||||
$this->trigger();
|
||||
} catch (Exception $e) {
|
||||
$this->con->unlock();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterAddFeed
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAfterAddFeed', $cur);
|
||||
|
||||
return $cur->feed_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick enable / disable feed.
|
||||
*
|
||||
* @param integer $id Feed Id
|
||||
* @param boolean $enable Enable or disable feed
|
||||
* @param integer $time Force update time
|
||||
*/
|
||||
public function enableFeed($id, $enable = true, $time = null)
|
||||
{
|
||||
try {
|
||||
$id = (int) $id;
|
||||
|
||||
if ($id < 1) {
|
||||
throw new Exception(__('No such ID'));
|
||||
}
|
||||
|
||||
$cur = $this->openCursor();
|
||||
$this->con->writeLock($this->table);
|
||||
|
||||
$cur->feed_upddt = date('Y-m-d H:i:s');
|
||||
$cur->feed_status = (int) $enable;
|
||||
if (null !== $time) {
|
||||
$cur->feed_upd_last = (int) $time;
|
||||
}
|
||||
|
||||
$cur->update(sprintf(
|
||||
"WHERE feed_id = %s AND blog_id = '%s' ",
|
||||
$id,
|
||||
$this->blog
|
||||
));
|
||||
$this->con->unlock();
|
||||
$this->trigger();
|
||||
} catch (Exception $e) {
|
||||
$this->con->unlock();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterEnableFeed
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerAfterEnableFeed', $id, $enable, $time);
|
||||
}
|
||||
|
||||
#
|
||||
/**
|
||||
* Delete record (this not deletes post).
|
||||
*
|
||||
* @param integer $id Feed Id
|
||||
*/
|
||||
public function delFeed($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
|
||||
if ($id < 1) {
|
||||
throw new Exception(__('No such ID'));
|
||||
}
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerBeforeDelFeed
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerBeforeDelFeed', $id);
|
||||
|
||||
$this->con->execute(sprintf(
|
||||
"DELETE FROM %s WHERE feed_id = %s AND blog_id = '%s' ",
|
||||
$this->table,
|
||||
$id,
|
||||
$this->blog
|
||||
));
|
||||
$this->trigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get related posts.
|
||||
*
|
||||
* @param array $params Query params
|
||||
* @param boolean $count_only Return only result count
|
||||
* @return null|dcRecord record instance
|
||||
*/
|
||||
public function getPostsByFeed($params = [], $count_only = false)
|
||||
{
|
||||
if (!isset($params['feed_id'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$sql = new dcSelectStatement();
|
||||
$sql->join(
|
||||
(new dcJoinStatement())
|
||||
->type('LEFT')
|
||||
->from(dcCore::app()->prefix . dcMeta::META_TABLE_NAME . ' F')
|
||||
->on('P.post_id = F.post_id')
|
||||
->statement()
|
||||
);
|
||||
|
||||
$params['sql'] = "AND P.blog_id = '" . $this->blog . "' " .
|
||||
"AND F.meta_type = 'zoneclearfeed_id' " .
|
||||
"AND F.meta_id = '" . $this->con->escape($params['feed_id']) . "' ";
|
||||
|
||||
unset($params['feed_id']);
|
||||
|
||||
return dcCore::app()->blog->getPosts($params, $count_only, $sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feed record.
|
||||
*
|
||||
* @param array $params Query params
|
||||
* @param boolean $count_only Return only result count
|
||||
* @return dcRecord record instance
|
||||
*/
|
||||
public function getFeeds($params = [], $count_only = false)
|
||||
{
|
||||
if ($count_only) {
|
||||
$strReq = 'SELECT count(Z.feed_id) ';
|
||||
} else {
|
||||
$content_req = '';
|
||||
if (!empty($params['columns']) && is_array($params['columns'])) {
|
||||
$content_req .= implode(', ', $params['columns']) . ', ';
|
||||
}
|
||||
|
||||
$strReq = 'SELECT Z.feed_id, Z.feed_creadt, Z.feed_upddt, Z.feed_type, ' .
|
||||
'Z.blog_id, Z.cat_id, ' .
|
||||
'Z.feed_upd_int, Z.feed_upd_last, Z.feed_status, ' .
|
||||
$content_req .
|
||||
'LOWER(Z.feed_name) as lowername, Z.feed_name, Z.feed_desc, ' .
|
||||
'Z.feed_url, Z.feed_feed, Z.feed_get_tags, ' .
|
||||
'Z.feed_tags, Z.feed_owner, Z.feed_tweeter, Z.feed_lang, ' .
|
||||
'Z.feed_nb_out, Z.feed_nb_in, ' .
|
||||
'C.cat_title, C.cat_url, C.cat_desc ';
|
||||
}
|
||||
|
||||
$strReq .= 'FROM ' . $this->table . ' Z ' .
|
||||
'LEFT OUTER JOIN ' . dcCore::app()->prefix . dcCategories::CATEGORY_TABLE_NAME . ' C ON Z.cat_id = C.cat_id ';
|
||||
|
||||
if (!empty($params['from'])) {
|
||||
$strReq .= $params['from'] . ' ';
|
||||
}
|
||||
|
||||
$strReq .= "WHERE Z.blog_id = '" . $this->blog . "' ";
|
||||
|
||||
if (isset($params['feed_type'])) {
|
||||
$strReq .= "AND Z.feed_type = '" . $this->con->escape($params['type']) . "' ";
|
||||
} else {
|
||||
$strReq .= "AND Z.feed_type = 'feed' ";
|
||||
}
|
||||
|
||||
if (!empty($params['feed_id'])) {
|
||||
if (is_array($params['feed_id'])) {
|
||||
array_walk($params['feed_id'], function (&$v, $k) { if ($v !== null) { $v = (int) $v; }});
|
||||
} else {
|
||||
$params['feed_id'] = [(int) $params['feed_id']];
|
||||
}
|
||||
$strReq .= 'AND Z.feed_id ' . $this->con->in($params['feed_id']);
|
||||
}
|
||||
|
||||
if (isset($params['feed_feed'])) {
|
||||
$strReq .= "AND Z.feed_feed = '" . $this->con->escape($params['feed_feed']) . "' ";
|
||||
}
|
||||
if (isset($params['feed_url'])) {
|
||||
$strReq .= "AND Z.feed_url = '" . $this->con->escape($params['feed_url']) . "' ";
|
||||
}
|
||||
if (isset($params['feed_status'])) {
|
||||
$strReq .= 'AND Z.feed_status = ' . ((int) $params['feed_status']) . ' ';
|
||||
}
|
||||
|
||||
if (!empty($params['q'])) {
|
||||
$q = $this->con->escape(str_replace('*', '%', strtolower($params['q'])));
|
||||
$strReq .= "AND LOWER(Z.feed_name) LIKE '" . $q . "' ";
|
||||
}
|
||||
|
||||
if (!empty($params['sql'])) {
|
||||
$strReq .= $params['sql'] . ' ';
|
||||
}
|
||||
|
||||
if (!$count_only) {
|
||||
if (!empty($params['order'])) {
|
||||
$strReq .= 'ORDER BY ' . $this->con->escape($params['order']) . ' ';
|
||||
} else {
|
||||
$strReq .= 'ORDER BY Z.feed_upddt DESC ';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$count_only && !empty($params['limit'])) {
|
||||
$strReq .= $this->con->limit($params['limit']);
|
||||
}
|
||||
|
||||
$rs = $this->con->select($strReq);
|
||||
|
||||
return $rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next table id.
|
||||
*
|
||||
* @return integer Next id
|
||||
*/
|
||||
private function getNextId()
|
||||
{
|
||||
return $this->con->select(
|
||||
'SELECT MAX(feed_id) FROM ' . $this->table
|
||||
)->f(0) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock a file to see if an update is ongoing.
|
||||
*
|
||||
* @return boolean True if file is locked
|
||||
*/
|
||||
public function lockUpdate()
|
||||
{
|
||||
try {
|
||||
# Need flock function
|
||||
if (!function_exists('flock')) {
|
||||
throw new Exception("Can't call php function named flock");
|
||||
}
|
||||
# Cache writable ?
|
||||
if (!is_writable(DC_TPL_CACHE)) {
|
||||
throw new Exception("Can't write in cache fodler");
|
||||
}
|
||||
# Set file path
|
||||
$f_md5 = md5($this->blog);
|
||||
$cached_file = sprintf(
|
||||
'%s/%s/%s/%s/%s.txt',
|
||||
DC_TPL_CACHE,
|
||||
'periodical',
|
||||
substr($f_md5, 0, 2),
|
||||
substr($f_md5, 2, 2),
|
||||
$f_md5
|
||||
);
|
||||
# Real path
|
||||
$cached_file = path::real($cached_file, false);
|
||||
# Make dir
|
||||
if (!is_dir(dirname($cached_file))) {
|
||||
files::makeDir(dirname($cached_file), true);
|
||||
}
|
||||
# Make file
|
||||
if (!file_exists($cached_file)) {
|
||||
!$fp = @fopen($cached_file, 'w');
|
||||
if ($fp === false) {
|
||||
throw new Exception("Can't create file");
|
||||
}
|
||||
fwrite($fp, '1', strlen('1'));
|
||||
fclose($fp);
|
||||
}
|
||||
# Open file
|
||||
if (!($fp = @fopen($cached_file, 'r+'))) {
|
||||
throw new Exception("Can't open file");
|
||||
}
|
||||
# Lock file
|
||||
if (!flock($fp, LOCK_EX)) {
|
||||
throw new Exception("Can't lock file");
|
||||
}
|
||||
$this->lock = $fp;
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock file of update process.
|
||||
*/
|
||||
public function unlockUpdate()
|
||||
{
|
||||
@fclose($this->lock);
|
||||
$this->lock = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and add/update post related to record if needed.
|
||||
*
|
||||
* @param integer $id Feed Id
|
||||
* @param boolean $throw Throw exception or end silently
|
||||
* @return boolean True if process succeed
|
||||
*/
|
||||
public function checkFeedsUpdate($id = null, $throw = false)
|
||||
{
|
||||
$s = dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)));
|
||||
|
||||
# Not configured
|
||||
if (!$s->active || !$s->user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# Limit to one update at a time
|
||||
try {
|
||||
$this->lockUpdate();
|
||||
} catch (Exception $e) {
|
||||
if ($throw) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
dt::setTZ(dcCore::app()->blog->settings->system->blog_timezone);
|
||||
$time = time();
|
||||
|
||||
# All feeds or only one (from admin)
|
||||
$f = !$id ?
|
||||
$this->getFeeds(['feed_status' => 1, 'order' => 'feed_upd_last ASC']) :
|
||||
$this->getFeeds(['feed_id' => $id]);
|
||||
|
||||
# No feed
|
||||
if ($f->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$enabled = false;
|
||||
$updates = false;
|
||||
$loop_mem = [];
|
||||
|
||||
$limit = abs((int) $s->update_limit);
|
||||
if ($limit < 1) {
|
||||
$limit = 10;
|
||||
}
|
||||
$i = 0;
|
||||
|
||||
$cur_post = $this->con->openCursor(dcCore::app()->prefix . dcBlog::POST_TABLE_NAME);
|
||||
$cur_meta = $this->con->openCursor(dcCore::app()->prefix . dcMeta::META_TABLE_NAME);
|
||||
|
||||
while ($f->fetch()) {
|
||||
# Check if feed need update
|
||||
if ($id
|
||||
|| $i < $limit && $f->feed_status == 1 && ($time > $f->feed_upd_last + $f->feed_upd_int)
|
||||
) {
|
||||
if (!$enabled) {
|
||||
# Set feeds user
|
||||
$this->enableUser(true);
|
||||
$enabled = true;
|
||||
}
|
||||
$i++;
|
||||
$feed = self::readFeed($f->feed_feed);
|
||||
|
||||
# Nothing to parse
|
||||
if (!$feed) {
|
||||
# Keep active empty feed or disable it ?
|
||||
if (!$s->keep_empty_feed) {
|
||||
$this->enableFeed($f->feed_id, false);
|
||||
} else {
|
||||
# Set update time of this feed
|
||||
$this->enableFeed($f->feed_id, true, $time);
|
||||
}
|
||||
$i++;
|
||||
|
||||
# Not updated since last visit
|
||||
} elseif (!$id
|
||||
&& '' != $feed->pubdate
|
||||
&& strtotime($feed->pubdate) < $f->feed_upd_last
|
||||
) {
|
||||
# Set update time of this feed
|
||||
$this->enableFeed($f->feed_id, true, $time);
|
||||
$i++;
|
||||
} else {
|
||||
# Set update time of this feed
|
||||
$this->enableFeed($f->feed_id, $f->feed_status, $time);
|
||||
|
||||
$this->con->begin();
|
||||
|
||||
foreach ($feed->items as $item) {
|
||||
$item_TS = $item->TS ? $item->TS : $time;
|
||||
|
||||
// I found that mercurial atom feed did not repect standard
|
||||
$item_link = @$item->link;
|
||||
if (!$item_link) {
|
||||
$item_link = @$item->guid;
|
||||
}
|
||||
# Unknow feed item link
|
||||
if (!$item_link) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item_link = $this->con->escape($item_link);
|
||||
$is_new_published_entry = false;
|
||||
|
||||
# Not updated since last visit
|
||||
if (!$id && $item_TS < $f->feed_upd_last) {
|
||||
continue;
|
||||
}
|
||||
|
||||
# Fix loop twin
|
||||
if (in_array($item_link, $loop_mem)) {
|
||||
continue;
|
||||
}
|
||||
$loop_mem[] = $item_link;
|
||||
|
||||
# Check if entry exists
|
||||
$old_post = $this->con->select(
|
||||
'SELECT P.post_id, P.post_status ' .
|
||||
'FROM ' . dcCore::app()->prefix . dcBlog::POST_TABLE_NAME . ' P ' .
|
||||
'INNER JOIN ' . dcCore::app()->prefix . dcMeta::META_TABLE_NAME . ' M ' .
|
||||
'ON P.post_id = M.post_id ' .
|
||||
"WHERE blog_id='" . $this->blog . "' " .
|
||||
"AND meta_type = 'zoneclearfeed_url' " .
|
||||
"AND meta_id = '" . $item_link . "' "
|
||||
);
|
||||
|
||||
# Prepare entry cursor
|
||||
$cur_post->clean();
|
||||
$cur_post->post_dt = date('Y-m-d H:i:s', $item_TS);
|
||||
if ($f->cat_id) {
|
||||
$cur_post->cat_id = $f->cat_id;
|
||||
}
|
||||
$post_content = $item->content ? $item->content : $item->description;
|
||||
$cur_post->post_format = 'xhtml';
|
||||
$cur_post->post_content = html::absoluteURLs($post_content, $feed->link);
|
||||
$cur_post->post_title = $item->title ? $item->title : text::cutString(html::clean($cur_post->post_content), 60);
|
||||
$creator = $item->creator ? $item->creator : $f->feed_owner;
|
||||
|
||||
try {
|
||||
# Create entry
|
||||
if ($old_post->isEmpty()) {
|
||||
# Post
|
||||
$cur_post->user_id = dcCore::app()->auth->userID();
|
||||
$cur_post->post_format = 'xhtml';
|
||||
$cur_post->post_status = (int) $s->post_status_new;
|
||||
$cur_post->post_open_comment = 0;
|
||||
$cur_post->post_open_tb = 0;
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerBeforePostCreate
|
||||
dcCore::app()->callBehavior(
|
||||
'zoneclearFeedServerBeforePostCreate',
|
||||
$cur_post
|
||||
);
|
||||
|
||||
$post_id = dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->blog, 'addPost'],
|
||||
$cur_post
|
||||
);
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterPostCreate
|
||||
dcCore::app()->callBehavior(
|
||||
'zoneclearFeedServerAfterPostCreate',
|
||||
$cur_post,
|
||||
$post_id
|
||||
);
|
||||
|
||||
# Auto tweet new post
|
||||
if ($cur_post->post_status == 1) {
|
||||
$is_new_published_entry = true;
|
||||
}
|
||||
|
||||
# Update entry
|
||||
} else {
|
||||
$post_id = $old_post->post_id;
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerBeforePostUpdate
|
||||
dcCore::app()->callBehavior(
|
||||
'zoneclearFeedServerBeforePostUpdate',
|
||||
$cur_post,
|
||||
$post_id
|
||||
);
|
||||
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->blog, 'updPost'],
|
||||
$post_id,
|
||||
$cur_post
|
||||
);
|
||||
|
||||
# Quick delete old meta
|
||||
$this->con->execute(
|
||||
'DELETE FROM ' . dcCore::app()->prefix . dcMeta::META_TABLE_NAME . ' ' .
|
||||
'WHERE post_id = ' . $post_id . ' ' .
|
||||
"AND meta_type LIKE 'zoneclearfeed_%' "
|
||||
);
|
||||
|
||||
# Delete old tags
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->meta, 'delPostMeta'],
|
||||
$post_id,
|
||||
'tag'
|
||||
);
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterPostUpdate
|
||||
dcCore::app()->callBehavior(
|
||||
'zoneclearFeedServerAfterPostUpdate',
|
||||
$cur_post,
|
||||
$post_id
|
||||
);
|
||||
}
|
||||
|
||||
# Quick add new meta
|
||||
$meta = new ArrayObject();
|
||||
$meta->tweeter = $f->feed_tweeter;
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->post_id = $post_id;
|
||||
$cur_meta->meta_type = 'zoneclearfeed_url';
|
||||
$cur_meta->meta_id = $meta->url = $item_link;
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->post_id = $post_id;
|
||||
$cur_meta->meta_type = 'zoneclearfeed_author';
|
||||
$cur_meta->meta_id = $meta->author = $creator;
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->post_id = $post_id;
|
||||
$cur_meta->meta_type = 'zoneclearfeed_site';
|
||||
$cur_meta->meta_id = $meta->site = $f->feed_url;
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->post_id = $post_id;
|
||||
$cur_meta->meta_type = 'zoneclearfeed_sitename';
|
||||
$cur_meta->meta_id = $meta->sitename = $f->feed_name;
|
||||
$cur_meta->insert();
|
||||
|
||||
$cur_meta->clean();
|
||||
$cur_meta->post_id = $post_id;
|
||||
$cur_meta->meta_type = 'zoneclearfeed_id';
|
||||
$cur_meta->meta_id = $meta->id = $f->feed_id;
|
||||
$cur_meta->insert();
|
||||
|
||||
# Add new tags
|
||||
$tags = dcCore::app()->meta->splitMetaValues($f->feed_tags);
|
||||
if ($f->feed_get_tags) {
|
||||
# Some feed subjects contains more than one tag
|
||||
foreach ($item->subject as $subjects) {
|
||||
$tmp = dcCore::app()->meta->splitMetaValues($subjects);
|
||||
$tags = array_merge($tags, $tmp);
|
||||
}
|
||||
$tags = array_unique($tags);
|
||||
}
|
||||
$formated_tags = [];
|
||||
foreach ($tags as $tag) {
|
||||
# Change tags case
|
||||
switch ((int) $s->tag_case) {
|
||||
case 3: $tag = strtoupper($tag);
|
||||
|
||||
break;
|
||||
case 2: $tag = strtolower($tag);
|
||||
|
||||
break;
|
||||
case 1: $tag = ucfirst(strtolower($tag));
|
||||
|
||||
break;
|
||||
default: /* do nothing */ break;
|
||||
}
|
||||
if (!in_array($tag, $formated_tags)) {
|
||||
$formated_tags[] = $tag;
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->meta, 'delPostMeta'],
|
||||
$post_id,
|
||||
'tag',
|
||||
dcMeta::sanitizeMetaID($tag)
|
||||
);
|
||||
dcCore::app()->auth->sudo(
|
||||
[dcCore::app()->meta, 'setPostMeta'],
|
||||
$post_id,
|
||||
'tag',
|
||||
dcMeta::sanitizeMetaID($tag)
|
||||
);
|
||||
}
|
||||
}
|
||||
$meta->tags = $formated_tags;
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerAfterFeedUpdate
|
||||
dcCore::app()->callBehavior(
|
||||
'zoneclearFeedServerAfterFeedUpdate',
|
||||
$is_new_published_entry,
|
||||
$cur_post,
|
||||
$meta
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
$this->con->rollback();
|
||||
$this->enableUser(false);
|
||||
$this->unlockUpdate();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
$updates = true;
|
||||
}
|
||||
$this->con->commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($enabled) {
|
||||
$this->enableUser(false);
|
||||
}
|
||||
$this->unlockUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permission to update post table.
|
||||
*
|
||||
* @param boolean $enable Enable or disable perm
|
||||
*/
|
||||
public function enableUser($enable = false)
|
||||
{
|
||||
# Enable
|
||||
if ($enable) {
|
||||
// backup current user
|
||||
$this->user = dcCore::app()->auth->userID();
|
||||
// set zcfs posts user
|
||||
if (!dcCore::app()->auth->checkUser((string) dcCore::app()->blog->settings->__get(basename(dirname('../' . __DIR__)))->user)) {
|
||||
throw new Exception('Unable to set user');
|
||||
}
|
||||
# Disable
|
||||
} else {
|
||||
dcCore::app()->auth = null;
|
||||
dcCore::app()->auth = new dcAuth();
|
||||
// restore current user
|
||||
dcCore::app()->auth->checkUser($this->user ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and parse external feeds.
|
||||
*
|
||||
* @param string $f Feed URL
|
||||
* @return feedParser|false Parsed feed
|
||||
*/
|
||||
public static function readFeed($f)
|
||||
{
|
||||
try {
|
||||
$feed_reader = new feedReader();
|
||||
$feed_reader->setCacheDir(DC_TPL_CACHE);
|
||||
$feed_reader->setTimeout(self::$nethttp_timeout);
|
||||
$feed_reader->setMaxRedirects(self::$nethttp_maxredirect);
|
||||
$feed_reader->setUserAgent(self::$nethttp_agent);
|
||||
|
||||
return $feed_reader->parse($f);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger.
|
||||
*/
|
||||
private function trigger()
|
||||
{
|
||||
dcCore::app()->blog->triggerBlog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an URL is well formed
|
||||
*
|
||||
* @param string $url URL
|
||||
* @return Boolean True if URL is allowed
|
||||
*/
|
||||
public static function validateURL($url)
|
||||
{
|
||||
return false !== strpos($url, 'http://')
|
||||
|| false !== strpos($url, 'https://');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full URL.
|
||||
*
|
||||
* Know bugs: anchor is not well parsed.
|
||||
*
|
||||
* @param string $root Root URL
|
||||
* @param string $url An URL
|
||||
* @return string Parse URL
|
||||
*/
|
||||
public static function absoluteURL($root, $url)
|
||||
{
|
||||
$host = preg_replace(
|
||||
'|^([a-z]{3,}://)(.*?)/(.*)$|',
|
||||
'$1$2',
|
||||
$root
|
||||
);
|
||||
|
||||
$parse = parse_url($url);
|
||||
|
||||
if (empty($parse['scheme'])) {
|
||||
if (strpos($url, '/') === 0) {
|
||||
$url = $host . $url;
|
||||
} elseif (strpos($url, '#') === 0) {
|
||||
$url = $root . $url;
|
||||
} elseif (preg_match('|/$|', $root)) {
|
||||
$url = $root . $url;
|
||||
} else {
|
||||
$url = dirname($root) . '/' . $url;
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of feeds status.
|
||||
*
|
||||
* @return array List of names/values of feeds status
|
||||
*/
|
||||
public static function getAllStatus()
|
||||
{
|
||||
return [
|
||||
__('Disabled') => '0',
|
||||
__('Enabled') => '1',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of predefined interval.
|
||||
*
|
||||
* @return array List of Name/time of intervals
|
||||
*/
|
||||
public static function getAllUpdateInterval()
|
||||
{
|
||||
return [
|
||||
__('Every hour') => 3600,
|
||||
__('Every two hours') => 7200,
|
||||
__('Two times per day') => 43200,
|
||||
__('Every day') => 86400,
|
||||
__('Every two days') => 172800,
|
||||
__('Every week') => 604800,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of (super)admins of current blog.
|
||||
*
|
||||
* @return array List of UserCNs/UserIds
|
||||
*/
|
||||
public function getAllBlogAdmins()
|
||||
{
|
||||
$admins = [];
|
||||
|
||||
# Get super admins
|
||||
$rs = $this->con->select(
|
||||
'SELECT user_id, user_super, user_name, user_firstname, user_displayname ' .
|
||||
'FROM ' . $this->con->escapeSystem(dcCore::app()->prefix . dcAuth::USER_TABLE_NAME) . ' ' .
|
||||
'WHERE user_super = 1 AND user_status = 1 '
|
||||
);
|
||||
|
||||
if (!$rs->isEmpty()) {
|
||||
while ($rs->fetch()) {
|
||||
$user_cn = dcUtils::getUserCN(
|
||||
$rs->user_id,
|
||||
$rs->user_name,
|
||||
$rs->user_firstname,
|
||||
$rs->user_displayname
|
||||
);
|
||||
$admins[$user_cn . ' (super admin)'] = $rs->user_id;
|
||||
}
|
||||
}
|
||||
|
||||
# Get admins
|
||||
$rs = $this->con->select(
|
||||
'SELECT U.user_id, U.user_super, U.user_name, U.user_firstname, U.user_displayname ' .
|
||||
'FROM ' . $this->con->escapeSystem(dcCore::app()->prefix . dcAuth::USER_TABLE_NAME) . ' U ' .
|
||||
'LEFT JOIN ' . $this->con->escapeSystem(dcCore::app()->prefix . dcAuth::PERMISSIONS_TABLE_NAME) . ' P ' .
|
||||
'ON U.user_id=P.user_id ' .
|
||||
'WHERE U.user_status = 1 ' .
|
||||
"AND P.blog_id = '" . $this->blog . "' " .
|
||||
"AND P.permissions LIKE '%|admin|%' "
|
||||
);
|
||||
|
||||
if (!$rs->isEmpty()) {
|
||||
while ($rs->fetch()) {
|
||||
$user_cn = dcUtils::getUserCN(
|
||||
$rs->user_id,
|
||||
$rs->user_name,
|
||||
$rs->user_firstname,
|
||||
$rs->user_displayname
|
||||
);
|
||||
$admins[$user_cn . ' (admin)'] = $rs->user_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $admins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of urls where entries could be hacked.
|
||||
*
|
||||
* @return array List of names/types of URLs
|
||||
*/
|
||||
public static function getPublicUrlTypes()
|
||||
{
|
||||
$types = [];
|
||||
|
||||
# --BEHAVIOR-- zoneclearFeedServerPublicUrlTypes
|
||||
dcCore::app()->callBehavior('zoneclearFeedServerPublicUrlTypes', $types);
|
||||
|
||||
$types[__('Home page')] = 'default';
|
||||
$types[__('Entries pages')] = 'post';
|
||||
$types[__('Tags pages')] = 'tag';
|
||||
$types[__('Archives pages')] = 'archive';
|
||||
$types[__('Category pages')] = 'category';
|
||||
$types[__('Entries feed')] = 'feed';
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take care about plugin tweakurls (thanks Mathieu M.).
|
||||
*
|
||||
* @param cursor $cur cursor instance
|
||||
* @param integer $id Post Id
|
||||
*/
|
||||
public static function tweakurlsAfterPostCreate(cursor $cur, $id)
|
||||
{
|
||||
if (version_compare(dcCore::app()->plugins->moduleInfo('tweakurls', 'version'), '0.8', '>=')) {
|
||||
$cur->post_url = tweakUrls::tweakBlogURL($cur->post_url);
|
||||
dcCore::app()->auth->sudo([dcCore::app()->blog, 'updPost'], $id, $cur);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue