From 627d0b876db3668aca6fd9b1dba0ac9cb47e4aae Mon Sep 17 00:00:00 2001 From: brol Date: Sat, 25 Apr 2015 21:25:03 +0200 Subject: [PATCH] 2015.04.25 --- README.md | 29 +- _admin.php | 259 ++++++ _config.php | 215 +++++ _define.php | 36 + _install.php | 98 +++ _prepend.php | 55 ++ _public.php | 735 +++++++++++++++++ _uninstall.php | 83 ++ _widgets.php | 326 ++++++++ changelog | 124 +++ cron-script.php | 105 +++ default-templates/currywurst/zcfeeds.html | 68 ++ default-templates/mustek/zcfeeds.html | 87 ++ default-templates/zcfsupd.js | 32 + icon-big-update.png | Bin 0 -> 1580 bytes icon-big.png | Bin 0 -> 1637 bytes icon.png | Bin 0 -> 411 bytes inc/class.zcfs.feedsactions.php | 389 +++++++++ inc/class.zoneclear.feed.server.php | 933 ++++++++++++++++++++++ inc/lib.zcfs.list.php | 204 +++++ inc/lib.zcfs.socialmewriter.php | 148 ++++ inc/lib.zcfsr.activityreport.php | 169 ++++ index.php | 856 ++++++++++++++++++++ js/feedsfilter.js | 31 + js/post.js | 7 + js/postsfilter.js | 31 + locales/en/help/zoneclearFeedServer.html | 15 + locales/en/resources.php | 17 + locales/fr/help/zoneclearFeedServer.html | 15 + locales/fr/main.po | 548 +++++++++++++ locales/fr/resources.php | 17 + 31 files changed, 5630 insertions(+), 2 deletions(-) create mode 100644 _admin.php create mode 100644 _config.php create mode 100644 _define.php create mode 100644 _install.php create mode 100644 _prepend.php create mode 100644 _public.php create mode 100644 _uninstall.php create mode 100644 _widgets.php create mode 100644 changelog create mode 100644 cron-script.php create mode 100644 default-templates/currywurst/zcfeeds.html create mode 100644 default-templates/mustek/zcfeeds.html create mode 100644 default-templates/zcfsupd.js create mode 100644 icon-big-update.png create mode 100644 icon-big.png create mode 100644 icon.png create mode 100644 inc/class.zcfs.feedsactions.php create mode 100644 inc/class.zoneclear.feed.server.php create mode 100644 inc/lib.zcfs.list.php create mode 100644 inc/lib.zcfs.socialmewriter.php create mode 100644 inc/lib.zcfsr.activityreport.php create mode 100644 index.php create mode 100644 js/feedsfilter.js create mode 100644 js/post.js create mode 100644 js/postsfilter.js create mode 100644 locales/en/help/zoneclearFeedServer.html create mode 100644 locales/en/resources.php create mode 100644 locales/fr/help/zoneclearFeedServer.html create mode 100644 locales/fr/main.po create mode 100644 locales/fr/resources.php diff --git a/README.md b/README.md index 83286d4..cc8d994 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,27 @@ -# zoneclearFeedServer -Mixer votre blog avec un planet +# README + +## WHAT IS ZONECLEARFEEDSERVER ? + +"zoneclear Feeds server" is a plugin for the open-source +web publishing software called Dotclear. + +It mix your blog with a feeds planet. + +## REQUIREMENTS + + zoneclearFeedServer requires: + + * admin perms for configuration + * admin perms to manager feeds + * Dotclear 2.7 + +## USAGE + +First install zoneclearFeedServer, manualy from a zip package or from +Dotaddict repository. (See Dotclear's documentation to know how do this) + +Go to ''plugins manager'', expand zoneclearFeedServer information then +go to ''configure plugin'', fill in form. + +Once it's done you can manage your feeds from menu +''Feeds server'' on sidebar or you can add dashboard icon. diff --git a/_admin.php b/_admin.php new file mode 100644 index 0000000..228e8fc --- /dev/null +++ b/_admin.php @@ -0,0 +1,259 @@ +blog->settings->addNamespace('zoneclearFeedServer'); + +# Check if latest version is installed +if ($core->getVersion('zoneclearFeedServer') != + $core->plugins->moduleInfo('zoneclearFeedServer', 'version')) { + + return null; +} + +# Widgets +require_once dirname(__FILE__).'/_widgets.php'; + +# Admin menu +$_menu['Blog']->addItem( + __('Feeds server'), + 'plugin.php?p=zoneclearFeedServer', + 'index.php?pf=zoneclearFeedServer/icon.png', + preg_match( + '/plugin.php\?p=zoneclearFeedServer(&.*)?$/', + $_SERVER['REQUEST_URI'] + ), + $core->auth->check('admin', $core->blog->id) +); + +# Delete related info about feed post in meta table +$core->addBehavior( + 'adminBeforePostDelete', + array('zcfsAdminBehaviors', 'adminBeforePostDelete') +); + +if ($core->auth->check('admin', $core->blog->id)) { + + # Dashboard icon + $core->addBehavior( + 'adminDashboardFavorites', + array('zcfsAdminBehaviors', 'adminDashboardFavorites') + ); + + # Add info about feed on post page sidebar + $core->addBehavior( + 'adminPostHeaders', + array('zcfsAdminBehaviors', 'adminPostHeaders') + ); + $core->addBehavior( + 'adminPostFormItems', + array('zcfsAdminBehaviors', 'adminPostFormItems') + ); +} + +# Take care about tweakurls (thanks Mathieu M.) +if (version_compare($core->plugins->moduleInfo('tweakurls', 'version'), '0.8', '>=')) { + + $core->addbehavior( + 'zcfsAfterPostCreate', + array('zoneclearFeedServer', 'tweakurlsAfterPostCreate') + ); +} + +/** + * @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER + * @brief Mix your blog with a feeds planet - admin methods. + * @since 2.6 + */ +class zcfsAdminBehaviors +{ + /** + * Favorites. + * + * @param dcCore $core dcCore instance + * @param arrayObject $favs Array of favorites + */ + public static function adminDashboardFavorites(dcCore $core, $favs) + { + $favs->register('zcfs', array( + 'title' => __('Feeds server'), + 'url' => 'plugin.php?p=zoneclearFeedServer', + 'small-icon' => 'index.php?pf=zoneclearFeedServer/icon.png', + 'large-icon' => 'index.php?pf=zoneclearFeedServer/icon-big.png', + 'permissions' => 'usage,contentadmin', + 'active_cb' => array( + 'zcfsAdminBehaviors', + 'adminDashboardFavoritesActive' + ), + 'dashboard_cb' => array( + 'zcfsAdminBehaviors', + 'adminDashboardFavoritesCallback' + ) + )); + } + + /** + * Favorites selection. + * + * @param string $request Requested page + * @param array $params Requested parameters + */ + public static function adminDashboardFavoritesActive($request, $params) + { + return $request == 'plugin.php' + && isset($params['p']) + && $params['p'] == 'zoneclearFeedServer'; + } + + /** + * Favorites hack. + * + * @param dcCore $core dcCore instance + * @param arrayObject $fav Fav attributes + */ + public static function adminDashboardFavoritesCallback(dcCore $core, $fav) + { + $zcfs = new zoneclearFeedServer($core); + $count = $zcfs->getFeeds(array( + 'feed_status' => '0' + ), true)->f(0); + + if (!$count) { + + return null; + } + + $fav['title'] .= '
'.sprintf( + __('%s feed disabled', '%s feeds disabled', $count), + $count + ); + $fav['url'] = 'plugin.php?p=zoneclearFeedServer&part=feeds'. + '&sortby=feed_status&order=asc'; + $fav['large-icon'] = 'index.php?pf=zoneclearFeedServer'. + '/icon-big-update.png'; + } + + /** + * Add javascript for toggle to post edition page header. + * + * @return string Page header + */ + public static function adminPostHeaders() + { + return dcPage::jsLoad( + 'index.php?pf=zoneclearFeedServer/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; + } + + global $core; + + $url = $core->meta->getMetadata(array( + 'post_id' => $post->post_id, + 'meta_type' => 'zoneclearfeed_url', + 'limit' => 1 + )); + $url = $url->isEmpty() ? '' : $url->meta_id; + + if (!$url) { + + return null; + } + + $author = $core->meta->getMetadata(array( + 'post_id' => $post->post_id, + 'meta_type' => 'zoneclearfeed_author', + 'limit' => 1 + )); + $author = $author->isEmpty() ? '' : $author->meta_id; + + $site = $core->meta->getMetadata(array( + 'post_id' => $post->post_id, + 'meta_type' => 'zoneclearfeed_site', + 'limit' => 1 + )); + $site = $site->isEmpty() ? '' : $site->meta_id; + + $sitename = $core->meta->getMetadata(array( + 'post_id' => $post->post_id, + 'meta_type' => 'zoneclearfeed_sitename', + 'limit' => 1 + )); + $sitename = $sitename->isEmpty() ? '' : $sitename->meta_id; + + $edit = ''; + if ($core->auth->check('admin', $core->blog->id)) { + $fid = $core->meta->getMetadata(array( + 'post_id' => $post->post_id, + 'meta_type' => 'zoneclearfeed_id', + 'limit' => 1 + )); + if (!$fid->isEmpty()) { + $edit = + '

'.__('Edit this feed').'

'; + } + } + + $sidebar_items['options-box']['items']['zcfs'] = + '
'. + '
'.__('Feed source').'
'. + '

'. + ''.__('feed URL').' - '. + ''.__('site URL').''. + '

'. + $edit. + '
'; + } + + /** + * Delete related info about feed post in meta table. + * + * @param integer $post_id Post id + */ + public static function adminBeforePostDelete($post_id) + { + global $core; + + $core->con->execute( + 'DELETE FROM '.$core->prefix.'meta '. + 'WHERE post_id = '.((integer) $post_id).' '. + 'AND meta_type '.$core->con->in(array( + 'zoneclearfeed_url', + 'zoneclearfeed_author', + 'zoneclearfeed_site', + 'zoneclearfeed_sitename', + 'zoneclearfeed_id' + )).' ' + ); + } +} diff --git a/_config.php b/_config.php new file mode 100644 index 0000000..cc4914d --- /dev/null +++ b/_config.php @@ -0,0 +1,215 @@ +getURL().'#plugins' : $_REQUEST['redir']; + +# -- Get settings -- +$core->blog->settings->addNamespace('zoneclearFeedServer'); +$s = $core->blog->settings->zoneclearFeedServer; + +$active = (boolean) $s->zoneclearFeedServer_active; +$pub_active = (boolean) $s->zoneclearFeedServer_pub_active; +$post_status_new = (boolean) $s->zoneclearFeedServer_post_status_new; +$bhv_pub_upd = (integer) $s->zoneclearFeedServer_bhv_pub_upd; +$update_limit = (integer) $s->zoneclearFeedServer_update_limit; +$keep_empty_feed = (boolean) $s->zoneclearFeedServer_keep_empty_feed; +$tag_case = (integer) $s->zoneclearFeedServer_tag_case; +$post_full_tpl = @unserialize($s->zoneclearFeedServer_post_full_tpl); +$post_title_redir = @unserialize($s->zoneclearFeedServer_post_title_redir); +$feeduser = (string) $s->zoneclearFeedServer_user; + +if ($update_limit < 1) { + $update_limit = 10; +} +if (!is_array($post_full_tpl)) { + $post_full_tpl = array(); +} +if (!is_array($post_title_redir)) { + $post_title_redir = array(); +} + +$zc = new zoneclearFeedServer($core); + +# -- 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 = (integer) $_POST['bhv_pub_upd']; + $limit = abs((integer) $_POST['update_limit']); + $keep_empty_feed = !empty($_POST['keep_empty_feed']); + $tag_case = (integer) $_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; + } + + $s->put('zoneclearFeedServer_active', $active); + $s->put('zoneclearFeedServer_pub_active', $pub_active); + $s->put('zoneclearFeedServer_post_status_new', $post_status_new); + $s->put('zoneclearFeedServer_bhv_pub_upd', $bhv_pub_upd); + $s->put('zoneclearFeedServer_update_limit', $limit); + $s->put('zoneclearFeedServer_keep_empty_feed', $keep_empty_feed); + $s->put('zoneclearFeedServer_tag_case', $tag_case); + $s->put('zoneclearFeedServer_post_full_tpl', serialize($post_full_tpl)); + $s->put('zoneclearFeedServer_post_title_redir', serialize($post_title_redir)); + $s->put('zoneclearFeedServer_user', $feeduser); + + $core->blog->triggerBlog(); + + dcPage::addSuccessNotice( + __('Configuration successfully updated.') + ); + http::redirect( + $list->getURL('module=zoneclearFeedServer&conf=1&redir='. + $list->getRedir()) + ); + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } +} + +# -- Form combos -- +$combo_admins = $zc->getAllBlogAdmins(); +$combo_pubupd = array( + __('Disable') => 0, + __('Before display') => 1, + __('After display') => 2, + __('Through Ajax') => 3 +); +$combo_status = array( + __('Unpublished') => 0, + __('Published') => 1 +); +$combo_tagcase = array( + __('Keep source case') => 0, + __('First upper case') => 1, + __('All lower case') => 2, + __('All upper case') => 3 +); + +$pub_page_url = $core->blog->url.$core->url->getBase('zoneclearFeedsPage'); + +# -- Display form -- + +if (!is_writable(DC_TPL_CACHE)) { + echo + '

'. + __('Dotclear cache is not writable or not well configured!'). + '

'; + } + +echo ' + +
+

'.__('Activation').'

+ +

+
'; + +echo ' +
'; + +if ($core->blog->settings->zoneclearFeedServer->zoneclearFeedServer_pub_active) { + echo '

'.__('View the public list of feeds').'

'; +} + +echo ' +

'.__('Rules').'

+ +
+ +

'. +form::combo('post_status_new', $combo_status, $post_status_new).'

+ +

'. +form::combo('feeduser', $combo_admins, $feeduser).'

+ +

'. +form::combo('tag_case', $combo_tagcase, $tag_case).'

+ +
+ +

'. +form::combo('bhv_pub_upd', $combo_pubupd, $bhv_pub_upd).'

+ +

'. +form::field('update_limit', 6, 4, $update_limit).'

+ +

+ +

+ +
+ +

'.__('Redirect to original post on:').'

    '; + +foreach($zc->getPublicUrlTypes($core) as $k => $v) { + echo + '
  • '; +} +echo ' +
+ +
+ +

'.__('Show full content on:').'

    '; + +foreach($zc->getPublicUrlTypes($core) as $k => $v) { + echo + '
  • '; +} +echo ' +
+ +
+ +
+'; + +dcPage::helpBlock('zoneclearFeedServer'); \ No newline at end of file diff --git a/_define.php b/_define.php new file mode 100644 index 0000000..f4e41ed --- /dev/null +++ b/_define.php @@ -0,0 +1,36 @@ +registerModule( + /* Name */ + "zoneclearFeedServer", + /* Description*/ + "Mix your blog with a feeds planet", + /* Author */ + "Jean-Christian Denis, BG, Pierre Van Glabeke", + /* Version */ + '2015.04.25', + /* Properies */ + array( + 'permissions' => 'admin', + 'type' => 'plugin', + 'dc_min' => '2.7', + 'support' => 'http://forum.dotclear.org/viewtopic.php?pid=331158', + 'details' => 'http://plugins.dotaddict.org/dc2/details/zoneclearFeedServer' + ) +); \ No newline at end of file diff --git a/_install.php b/_install.php new file mode 100644 index 0000000..8489f7e --- /dev/null +++ b/_install.php @@ -0,0 +1,98 @@ +getVersion($mod_id), + $core->plugins->moduleInfo($mod_id, 'version'), + '>=' + )) { + + return null; + } + + # Check Dotclear version + if (!method_exists('dcUtils', 'versionsCompare') + || dcUtils::versionsCompare(DC_VERSION, $dc_min, '<', false)) { + throw new Exception(sprintf( + '%s requires Dotclear %s', $mod_id, $dc_min + )); + } + + # Tables + $t = new dbStruct($core->con, $core->prefix); + $t->zc_feed + ->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', 0, 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) + + ->primary('pk_zcfs', 'feed_id') + ->index('idx_zcfs_type', 'btree', 'feed_type') + ->index('idx_zcfs_blog', 'btree', 'blog_id'); + + $ti = new dbStruct($core->con, $core->prefix); + $changes = $ti->synchronize($t); + + # Settings + $core->blog->settings->addNamespace('zoneclearFeedServer'); + $s = $core->blog->settings->zoneclearFeedServer; + $s->put('zoneclearFeedServer_active', false, 'boolean', 'Enable zoneclearBlogServer', false, true); + $s->put('zoneclearFeedServer_pub_active', false, 'boolean', 'Enable public page of list of feeds', false, true); + $s->put('zoneclearFeedServer_post_status_new', true, 'boolean', 'Enable auto publish new posts', false, true); + $s->put('zoneclearFeedServer_bhv_pub_upd', 2, 'string', 'Auto update on public side (disable/before/after)', false, true); + $s->put('zoneclearFeedServer_update_limit', 1, 'integer', 'Number of feeds to update at one time', false, true); + $s->put('zoneclearFeedServer_keep_empty_feed', false, 'boolean', 'Keep active empty feeds', false, true); + $s->put('zoneclearFeedServer_tag_case', 0, 'integer', 'How to transform imported tags', false, true); + $s->put('zoneclearFeedServer_user', '', 'string','User id that has right on post', false, true); + $s->put('zoneclearFeedServer_post_full_tpl', serialize(array('post', 'category', 'tag', 'archive')), 'string', 'List of templates types for full feed', false, true); + $s->put('zoneclearFeedServer_post_title_redir', serialize(array('feed')), 'string', 'List of templates types for redirection to original post', false, true); + + # Set module version + $core->setVersion( + $mod_id, + $core->plugins->moduleInfo($mod_id, 'version') + ); + + return true; +} +catch (Exception $e) { + $core->error->add($e->getMessage()); + + return false; +} \ No newline at end of file diff --git a/_prepend.php b/_prepend.php new file mode 100644 index 0000000..5469c94 --- /dev/null +++ b/_prepend.php @@ -0,0 +1,55 @@ +getVersion('zoneclearFeedServer') != + $core->plugins->moduleInfo('zoneclearFeedServer', 'version')) { + + return null; +} + +$d = dirname(__FILE__).'/inc/'; + +$__autoload['zoneclearFeedServer'] = $d.'class.zoneclear.feed.server.php'; +$__autoload['zcfsFeedsList'] = $d.'lib.zcfs.list.php'; +$__autoload['zcfsEntriesList'] = $d.'lib.zcfs.list.php'; +$__autoload['zcfsFeedsActionsPage'] = $d.'class.zcfs.feedsactions.php'; +$__autoload['zcfsDefaultFeedsActions'] = $d.'class.zcfs.feedsactions.php'; + +# public url for page of description of the flux +$core->url->register( + 'zoneclearFeedsPage', + 'zcfeeds', + '^zcfeeds(.*?)$', + array('zcfsUrlHandler', 'zcFeedsPage') +); + +# Add to plugn soCialMe (writer part) +$__autoload['zcfsSoCialMeWriter'] = $d.'lib.zcfs.socialmewriter.php'; +$core->addBehavior( + 'soCialMeWriterMarker', + array('zcfsSoCialMeWriter', 'soCialMeWriterMarker') +); +$core->addBehavior( + 'zoneclearFeedServerAfterFeedUpdate', + array('zcfsSoCialMeWriter', 'zoneclearFeedServerAfterFeedUpdate') +); + +# Add to report on plugin activityReport +if (defined('ACTIVITY_REPORT')) { + require_once $d.'lib.zcfs.activityreport.php'; +} \ No newline at end of file diff --git a/_public.php b/_public.php new file mode 100644 index 0000000..725e165 --- /dev/null +++ b/_public.php @@ -0,0 +1,735 @@ +blog->settings->addNamespace('zoneclearFeedServer'); +$s = $core->blog->settings->zoneclearFeedServer; + +# Widgets +require_once dirname(__FILE__).'/_widgets.php'; + +$core->addBehavior( + 'coreBlogGetPosts', + array('zcfsPublicBehaviors', 'coreBlogGetPosts') +); + +if (!$s->zoneclearFeedServer_active) { + + return null; +} +if (1 == $s->zoneclearFeedServer_bhv_pub_upd) { + $core->addBehavior( + 'publicBeforeDocument', + array('zcfsPublicBehaviors', 'publicDocument') + ); +} +elseif (2 == $s->zoneclearFeedServer_bhv_pub_upd) { + $core->addBehavior( + 'publicAfterDocument', + array('zcfsPublicBehaviors', 'publicAfterDocument') + ); +} +elseif (3 == $s->zoneclearFeedServer_bhv_pub_upd) { + $core->addBehavior( + 'publicHeadContent', + array('zcfsPublicBehaviors', 'publicHeadContent') + ); +} + +# Take care about tweakurls (thanks Mathieu M.) +if (version_compare($core->plugins->moduleInfo('tweakurls', 'version'), '0.8', '>=')) { + $core->addbehavior( + 'zoneclearFeedServerAfterPostCreate', + array('zoneclearFeedServer', 'tweakurlsAfterPostCreate') + ); +} + +# Register tempalte blocks +$tpl_blocks = array( + 'Feeds', + 'FeedsFooter', + 'FeedsHeader', + 'FeedIf' +); +foreach($tpl_blocks as $v) { + $core->tpl->addBlock('zc'.$v, array('zcfsTemplate', $v)); +} + +# Register tempalte values +$tpl_values = array( + 'FeedsCount', + 'FeedsEntriesCount', + 'FeedEntriesCount', + 'FeedCategory', + 'FeedCategoryID', + 'FeedCategoryURL', + 'FeedCategoryShortURL', + 'FeedID', + 'FeedIfFirst', + 'FeedIfOdd', + 'FeedLang', + 'FeedName', + 'FeedOwner', + 'FeedDesc', + 'FeedSiteURL', + 'FeedFeedURL' +); +foreach($tpl_values as $v) { + $core->tpl->addValue('zc'.$v, array('zcfsTemplate', $v)); +} + +/** + * @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER + * @brief Mix your blog with a feeds planet - public methods. + * @since 2.6 + */ +class zcfsPublicBehaviors +{ + /** + * Remember others post extension. + * + * @param record $rs record instance + */ + public static function coreBlogGetPosts(record $rs) + { + $GLOBALS['beforeZcFeedRsExt'] = $rs->extensions(); + $rs->extend('zcfsRsExtPosts'); + } + + /** + * Update feeds after contents. + * + * @param dcCore $core dcCore instance + * @return string Document + */ + public static function publicAfterDocument(dcCore $core) + { + # Limit feeds update to home page et feed page + # Like publishScheduledEntries + if (!in_array($core->url->type, array('default', 'feed'))) { + + return null; + } + + self::publicDocument($core); + } + + /** + * Generic behavior for before and after public content. + * + * @param dcCore $core dcCore instance + * @return null NULL + */ + public static function publicDocument(dcCore $core) + { + $zc = new zoneclearFeedServer($core); + $zc->checkFeedsUpdate(); + + return null; + } + + /** + * Update feeds by an Ajax request (background). + * + * @param dcCore $core dcCore instance + * @param context $_ctx context instance + * @return string HTML content + */ + public static function publicHeadContent(dcCore $core, context $_ctx) + { + # Limit update to home page + if ($core->url->type != 'default') { + + return null; + } + + $blog_url = html::escapeJS( + $core->blog->url. + $core->url->getBase('zoneclearFeedsPage'). + '/zcfsupd' + ); + $blog_id = html::escapeJS($core->blog->id); + + echo + "\n \n". + " \n". + "\n"; + } +} + +/** + * @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER + * @brief Mix your blog with a feeds planet - rs methods. + * @since 2.6 + */ +class zcfsRsExtPosts extends rsExtPost +{ + /** + * Get feed meta. + * + * @param record $rs record instance + * @param string $info Feed info key + * @return string Feed info value + */ + public static function zcFeed($rs, $info) + { + $p = array( + 'post_id' => $rs->post_id, + 'meta_type' => 'zoneclearfeed_'.$info, + 'limit' => 1 + ); + $meta = $rs->core->meta->getMetadata($p); + + return $meta->isEmpty() ? null : $meta->meta_id; + } + + /** + * Call other rs extension. + * + * @param string $type Type of extension + * @param array $args Arguments + * @return mixed record extension ressource + */ + public static function zcFeedBrother($type, $args) + { + if (!empty($GLOBALS['beforeZcFeedRsExt'][$type])) { + $func = $GLOBALS['beforeZcFeedRsExt'][$type]; + } + elseif (is_callable('rsExtPostPublic', $type)) { + $func = array('rsExtPostPublic', $type); + } + else { + $func = array('rsExtPost', $type); + } + + return call_user_func_array($func, $args); + } + + /** + * Get author link from post to feed. + * + * @param record $rs record instance + * @return string Author link + */ + public static function getAuthorLink($rs) + { + $author = $rs->zcFeed('author'); + $site = $rs->zcFeed('site'); + $sitename = $rs->zcFeed('sitename'); + + return ($author && $sitename) ? + $author.' ('.$sitename.')' : + self::zcFeedBrother('getAuthorLink', array(&$rs)); + } + + /** + * Get author CN from post to feed. + * + * @param record $rs record instance + * @return string Author CN + */ + public static function getAuthorCN($rs) + { + $author = $rs->zcFeed('author'); + return $author ? + $author : + self::zcFeedBrother('getAuthorCN', array(&$rs)); + } + + /** + * Get post link from post to feed. + * + * @param record $rs record instance + * @return string Post link + */ + public static function getURL($rs) + { + $url = $rs->zcFeed('url'); + $types = @unserialize($rs->core->blog->settings->zoneclearFeedServer->zoneclearFeedServer_post_title_redir); + $full = is_array($types) && in_array($rs->core->url->type, $types); + + return $url && $full ? + zoneclearFeedServer::absoluteURL($rs->zcFeed('site'), $url) : + self::zcFeedBrother('getURL', array(&$rs)); + } + + /** + * Get post content from post to feed. + * + * @param record $rs record instance + * @return string Post content + */ + public static function getContent($rs, $absolute_urls=false) + { + $url = $rs->zcFeed('url'); + $sitename = $rs->zcFeed('sitename'); + $content = self::zcFeedBrother('getContent', array(&$rs,$absolute_urls)); + + if ($url && $sitename && $rs->post_type == 'post') { + $types = @unserialize($rs->core->blog->settings->zoneclearFeedServer->zoneclearFeedServer_post_full_tpl); + + if (is_array($types) && in_array($rs->core->url->type, $types)) { + + return $content . + '

'. + sprintf(__('Original post on %s'), $url, $sitename). + '

'; + } + else { + $content = context::remove_html($content); + $content = context::cut_string($content,350); + $content = html::escapeHTML($content); + + return + '

'.$content.'... '. + ''.__('Continue reading').'

'; + } + } + else { + + return $content; + } + } +} + +/** + * @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER + * @brief Mix your blog with a feeds planet - url handler methods. + * @since 2.6 + */ +class zcfsUrlHandler extends dcUrlHandlers +{ + /** + * Feeds source page and update methods. + * + * @param array $args Page arguments + * @return mixed + */ + public static function zcFeedsPage($args) + { + global $core, $_ctx; + $s = $core->blog->settings->zoneclearFeedServer; + + # Not active + if (!$s->zoneclearFeedServer_active) { + self::p404(); + + return null; + } + + # Update feeds (from ajax or other post resquest) + if ($args == '/zcfsupd' + && 3 == $s->zoneclearFeedServer_bhv_pub_upd + ) { + $msg = ''; + if (!empty($_POST['blogId']) + && html::escapeJS($core->blog->id) == $_POST['blogId'] + ) { + try { + $zc = new zoneclearFeedServer($core); + if ($zc->checkFeedsUpdate()) { + $msg = 'ok'. + 'Feeds updated successfully'; + } + } + catch (Exception $e) {} + } + if (empty($msg)) { + $msg = 'failed'. + 'Failed to update feeds'; + } + + header('Content-Type: application/xml; charset=UTF-8'); + echo + ''."\n". + ''."\n". + $msg."\n". + ''; + + exit(1); + } + # Server js + elseif ($args == '/zcfsupd.js' + && 3 == $s->zoneclearFeedServer_bhv_pub_upd + ) { + $core->tpl->setPath($core->tpl->getPath(), dirname(__FILE__).'/default-templates'); + self::serveDocument( + 'zcfsupd.js', + 'text/javascript', + false, + false + ); + } + # Server feeds description page + elseif (in_array($args, array('', '/')) + && $s->zoneclearFeedServer_pub_active + ) { + $tplset = $core->themes->moduleInfo($core->blog->settings->system->theme,'tplset'); + if (!empty($tplset) && is_dir(dirname(__FILE__).'/default-templates/'.$tplset)) { + $core->tpl->setPath($core->tpl->getPath(), dirname(__FILE__).'/default-templates/'.$tplset); + } else { + $core->tpl->setPath($core->tpl->getPath(), dirname(__FILE__).'/default-templates/'.DC_DEFAULT_TPLSET); + } + self::serveDocument('zcfeeds.html'); + } + # Unknow + else { + self::p404(); + } + + return null; + } +} + +/** + * @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER + * @brief Mix your blog with a feeds planet - template methods. + * @since 2.6 + */ +class zcfsTemplate +{ + public static function Feeds($a, $c) + { + $lastn = -1; + $p = ''; + if (isset($a['lastn'])) { + $lastn = abs((integer) $a['lastn'])+0; + $p .= "\$zcfs_params['limit'] = ".$lastn.";\n"; + } + if (isset($a['cat_id'])) { + $p .= "@\$zcfs_params['sql'] .= 'AND Z.cat_id = ".addslashes($a['cat_id'])." ';\n"; + } + if (isset($a['no_category'])) { + $p .= "@\$zcfs_params['sql'] .= 'AND Z.cat_id IS NULL ';\n"; + } + if (!empty($a['site_url'])) { + $p .= "\$zcfs_params['feed_url'] = '".addslashes($a['site_url'])."';\n"; + } + if (isset($a['feed_status'])) { + $p .= "\$zcfs_params['feed_status'] = ".((integer) $a['feed_status']).";\n"; + } + else { + $p .= "\$zcfs_params['feed_status'] = 1;\n"; + } + if (!empty($a['feed_url'])) { + $p .= "\$zcfs_params['feed_feed'] = '".addslashes($a['feed_url'])."';\n"; + } + if (isset($a['feed_owner'])) { + $p .= "@\$zcfs_params['sql'] .= \"AND Z.feed_owner = '".addslashes($a['author'])."' \";\n"; + } + + $sortby = 'feed_creadt'; + $order = 'desc'; + if (isset($a['sortby'])) { + switch ($a['sortby']) { + case 'name': $sortby = 'lowername'; break; + case 'owner' : $sortby = 'feed_owner'; break; + case 'date' : $sortby = 'feed_dt'; break; + case 'update' : $sortby = 'feed_upddt'; break; + case 'id' : $sortby = 'feed_id'; break; + } + } + if (isset($a['order']) + && preg_match('/^(desc|asc)$/i', $a['order']) + ) { + $order = $a['order']; + } + $p .= "\$zcfs_params['order'] = '".$sortby." ".$order."';\n"; + + return + 'feeds_params = $zcfs_params;'."\n". + '$zcfs = new zoneclearFeedServer($core);'."\n". + '$_ctx->feeds = $zcfs->getFeeds($zcfs_params); unset($zcfs_params,$zcfs);'."\n". + "?>\n". + 'feeds->fetch()) : ?>'.$c.'feeds = null; $_ctx->feeds_params = null; ?>'; + } + + public static function FeedIf($a,$c) + { + $if = array(); + + $operator = isset($a['operator']) ? self::getOperator($a['operator']) : '&&'; + + if (isset($a['type'])) { + $type = trim($a['type']); + $type = !empty($type) ? $type : 'feed'; + $if[] = '$_ctx->feeds->feed_type == "'.addslashes($type).'"'; + } + if (isset($a['site_url'])) { + $url = trim($a['feed_url']); + if (substr($url, 0, 1) == '!') { + $url = substr($url, 1); + $if[] = '$_ctx->feeds->feed_url != "'.addslashes($url).'"'; + } + else { + $if[] = '$_ctx->feeds->feed_url == "'.addslashes($url).'"'; + } + } + if (isset($a['feed_url'])) { + $url = trim($a['feed_feed']); + if (substr($url, 0, 1) == '!') { + $url = substr($url, 1); + $if[] = '$_ctx->feeds->feed_feed != "'.addslashes($url).'"'; + } + else { + $if[] = '$_ctx->feeds->feed_feed == "'.addslashes($url).'"'; + } + } + if (isset($a['category'])) { + $category = addslashes(trim($a['category'])); + if (substr($category, 0, 1) == '!') { + $category = substr($category, 1); + $if[] = '($_ctx->feeds->cat_url != "'.$category.'")'; + } + else { + $if[] = '($_ctx->feeds->cat_url == "'.$category.'")'; + } + } + if (isset($a['first'])) { + $sign = (boolean) $a['first'] ? '=' : '!'; + $if[] = '$_ctx->feeds->index() '.$sign.'= 0'; + } + if (isset($a['odd'])) { + $sign = (boolean) $a['odd'] ? '=' : '!'; + $if[] = '($_ctx->feeds->index()+1)%2 '.$sign.'= 1'; + } + if (isset($a['has_category'])) { + $sign = (boolean) $a['has_category'] ? '' : '!'; + $if[] = $sign.'$_ctx->feeds->cat_id'; + } + if (isset($a['has_description'])) { + $sign = (boolean) $a['has_description'] ? '' : '!'; + $if[] = $sign.'$_ctx->feeds->feed_desc'; + } + + return empty($if) ? + $c : + ''.$c.''; + } + + public static function FeedIfFirst($a) + { + $ret = isset($a['return']) ? $a['return'] : 'first'; + $ret = html::escapeHTML($ret); + + return + 'feeds->index() == 0) { '. + "echo '".addslashes($ret)."'; } ?>"; + } + + public static function FeedIfOdd($a) + { + $ret = isset($a['return']) ? $a['return'] : 'odd'; + $ret = html::escapeHTML($ret); + + return + 'feeds->index()+1)%2 == 1) { '. + "echo '".addslashes($ret)."'; } ?>"; + } + + public static function FeedDesc($a) + { + return self::getValue($a, '$_ctx->feeds->feed_desc'); + } + + public static function FeedOwner($a) + { + return self::getValue($a, '$_ctx->feeds->feed_owner'); + } + + public static function FeedCategory($a) + { + return self::getValue($a, '$_ctx->feeds->cat_title'); + } + + public static function FeedCategoryID($a) + { + return self::getValue($a, '$_ctx->feeds->cat_id'); + } + + public static function FeedCategoryURL($a) + { + return self::getValue($a, '$core->blog->url.$core->url->getBase(\'category\').\'/\'.html::sanitizeURL($_ctx->feeds->cat_url)'); + } + + public static function FeedCategoryShortURL($a) + { + return self::getValue($a, '$_ctx->feeds->cat_url'); + } + + public static function FeedID($a) + { + return self::getValue($a, '$_ctx->feeds->feed_id'); + } + + public static function FeedLang($a) + { + $f = $GLOBALS['core']->tpl->getFilters($a); + + return empty($a['full']) ? + 'feeds->feed_lang').'; ?>' + : + 'feeds->feed_lang])) { echo '.sprintf($f, '$langs[$_ctx->feeds->feed_lang]').'; } else { echo '.sprintf($f, '$_ctx->feeds->feed_lang').'; } unset($langs); ?>'; + } + + public static function FeedName($a) + { + return self::getValue($a, '$_ctx->feeds->feed_name'); + } + + public static function FeedSiteURL($a) + { + return self::getValue($a, '$_ctx->feeds->feed_url'); + } + + public static function FeedFeedURL($a) + { + return self::getValue($a, '$_ctx->feeds->feed_feed'); + } + + public static function FeedsHeader($a, $c) + { + return "feeds->isStart()) : ?>".$c.""; + } + + public static function FeedsFooter($a, $c) + { + return "feeds->isEnd()) : ?>".$c.""; + } + + public static function FeedsCount($a) + { + $none = 'no sources'; + $one = 'one source'; + $more = '%d sources'; + + if (isset($a['none'])) { + $none = addslashes($a['none']); + } + if (isset($a['one'])) { + $one = addslashes($a['one']); + } + if (isset($a['more'])) { + $more = addslashes($a['more']); + } + + return + "feeds->count(); \n". + "if (\$fcount == 0) {\n". + " printf(__('".$none."'),\$fcount);\n". + "} elseif (\$fcount == 1) {\n". + " printf(__('".$one."'),\$fcount);\n". + "} else {\n". + " printf(__('".$more."'),\$fcount);\n". + "} unset(\$fcount); ?>"; + } + + public static function FeedsEntriesCount($a) + { + $none = 'no entries'; + $one = 'one entry'; + $more = '%d entries'; + + if (isset($a['none'])) { + $none = addslashes($a['none']); + } + if (isset($a['one'])) { + $one = addslashes($a['one']); + } + if (isset($a['more'])) { + $more = addslashes($a['more']); + } + + return + "feeds->zc->getFeeds(); \n". + "if (!\$allfeeds->isEmpty()) { \n". + " while (\$allfeeds->fetch()) { ". + " \$fcount += (integer) \$_ctx->feeds->zc->getPostsByFeed(array('feed_id'=>\$allfeeds->feed_id),true)->f(0); ". + " } \n". + "} \n". + "if (\$fcount == 0) {\n". + " printf(__('".$none."'),\$fcount);\n". + "} elseif (\$fcount == 1) {\n". + " printf(__('".$one."'),\$fcount);\n". + "} else {\n". + " printf(__('".$more."'),\$fcount);\n". + "} unset(\$allfeeds,\$fcount); ?>"; + } + + public static function FeedEntriesCount($a) + { + $none = 'no entries'; + $one = 'one entry'; + $more = '%d entries'; + + if (isset($a['none'])) { + $none = addslashes($a['none']); + } + if (isset($a['one'])) { + $one = addslashes($a['one']); + } + if (isset($a['more'])) { + $more = addslashes($a['more']); + } + + return + "feeds->zc->getPostsByFeed(array('feed_id'=>\$_ctx->feeds->feed_id),true)->f(0); \n". + "if (\$fcount == 0) {\n". + " printf(__('".$none."'),\$fcount);\n". + "} elseif (\$fcount == 1) {\n". + " printf(__('".$one."'),\$fcount);\n". + "} else {\n". + " printf(__('".$more."'),\$fcount);\n". + "} unset(\$fcount); ?>"; + } + + protected static function getValue($a,$v) + { + return 'tpl->getFilters($a), $v).'; ?>'; + } + + protected static function getOperator($op) + { + switch (strtolower($op)) + { + case 'or': + case '||': + return '||'; + case 'and': + case '&&': + default: + return '&&'; + } + } +} \ No newline at end of file diff --git a/_uninstall.php b/_uninstall.php new file mode 100644 index 0000000..ccab7b1 --- /dev/null +++ b/_uninstall.php @@ -0,0 +1,83 @@ +addUserAction( + /* type */ 'settings', + /* action */ 'delete_all', + /* ns */ $mod_id, + /* desc */ __('delete all settings') +); +$this->addUserAction( + /* type */ 'tables', + /* action */ 'delete', + /* ns */ 'zc_feed', + /* desc */ __('delete table') +); +$this->addUserAction( + /* type */ 'plugins', + /* action */ 'delete', + /* ns */ $mod_id, + /* desc */ __('delete plugin files') +); +$this->addUserAction( + /* type */ 'versions', + /* action */ 'delete', + /* ns */ $mod_id, + /* desc */ __('delete the version number') +); + + +$this->addDirectAction( + /* type */ 'settings', + /* action */ 'delete_all', + /* ns */ $mod_id, + /* desc */ sprintf(__('delete all %s settings'), $mod_id) +); +$this->addDirectAction( + /* type */ 'tables', + /* action */ 'delete', + /* ns */ 'zc_feed', + /* desc */ sprintf(__('delete %s table'), $mod_id) +); +$this->addDirectAction( + /* type */ 'plugins', + /* action */ 'delete', + /* ns */ $mod_id, + /* desc */ sprintf(__('delete %s plugin files'), $mod_id) +); +$this->addDirectAction( + /* type */ 'versions', + /* action */ 'delete', + /* ns */ $mod_id, + /* desc */ sprintf(__('delete %s version number'), $mod_id) +); +$this->addDirectCallback( + /* function */ 'zoneclearfeedServerUninstall', + /* desc */ 'delete feeds relations' +); + +function zoneclearfeedServerUninstall($core, $id) +{ + if ($id != 'zoneclearFeedServer') { + + return null; + } + //... +} \ No newline at end of file diff --git a/_widgets.php b/_widgets.php new file mode 100644 index 0000000..f617a60 --- /dev/null +++ b/_widgets.php @@ -0,0 +1,326 @@ +addBehavior( + 'initWidgets', + array('zoneclearFeedServerWidget', 'adminSource') +); +$core->addBehavior( + 'initWidgets', + array('zoneclearFeedServerWidget', 'adminNumber') +); + +/** + * @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER + * @brief Mix your blog with a feeds planet - widgets methods. + * @since 2.6 + */ +class zoneclearFeedServerWidget +{ + /** + * Widget configuration for sources list. + * + * @param dcWidget $w dcWidget instance + */ + public static function adminSource($w) + { + $w->create( + 'zcfssource', + __('Feeds server: sources'), + array('zoneclearFeedServerWidget', 'publicSource'), + null, + __('List sources of feeds') + ); + $w->zcfssource->setting( + 'title', + __('Title:'), + __('Feeds sources'), + 'text' + ); + $w->zcfssource->setting( + 'sortby', + __('Order by:'), + 'feed_upd_last', + 'combo', + array( + __('Last update') => 'feed_upd_last', + __('Name') => 'lowername', + __('Create date') => 'feed_creadt' + ) + ); + $w->zcfssource->setting( + 'sort', + __('Sort:'), + 'desc', + 'combo', + array( + __('Ascending') => 'asc', + __('Descending') => 'desc' + ) + ); + $w->zcfssource->setting( + 'limit', + __('Limit:'), + 10, + 'text' + ); + $w->zcfssource->setting( + 'pagelink', + __('Add link to feeds page'), + 1, + 'check' + ); + $w->zcfssource->setting( + 'homeonly', + __('Display on:'), + 0, + 'combo', + array( + __('All pages') => 0, + __('Home page only') => 1, + __('Except on home page') => 2 + ) + ); + $w->zcfssource->setting( + 'content_only', + __('Content only'), + 0, + 'check' + ); + $w->zcfssource->setting( + 'class', + __('CSS class:'), + '' + ); + $w->zcfssource->setting('offline',__('Offline'),0,'check'); + } + + /** + * Widget configuration for feeds info. + * + * @param dcWidget $w dcWidget instance + */ + public static function adminNumber($w) + { + $w->create( + 'zcfsnumber', + __('Feeds server: numbers'), + array('zoneclearFeedServerWidget', 'publicNumber'), + null, + __('Show some numbers about feeds') + ); + $w->zcfsnumber->setting( + 'title', + __('Title:') + ,__('Feeds numbers'), + 'text' + ); + + # Feed + $w->zcfsnumber->setting( + 'feed_show', + __('Show feeds count'), + 1, + 'check' + ); + $w->zcfsnumber->setting( + 'feed_title', + __('Title for feeds count:'), + __('Feeds:'), + 'text' + ); + + # Entry + $w->zcfsnumber->setting( + 'entry_show', + __('Show entries count'), + 1, + 'check' + ); + $w->zcfsnumber->setting( + 'entry_title', + __('Title for entries count:'), + __('Entries:'), + 'text' + ); + + $w->zcfsnumber->setting( + 'homeonly', + __('Display on:'), + 0, + 'combo', + array( + __('All pages') => 0, + __('Home page only') => 1, + __('Except on home page') => 2 + ) + ); + $w->zcfsnumber->setting( + 'content_only', + __('Content only'), + 0, + 'check' + ); + $w->zcfsnumber->setting( + 'class', + __('CSS class:'), + '' + ); + $w->zcfsnumber->setting('offline',__('Offline'),0,'check'); + } + + /** + * Widget for sources list. + * + * @param dcWidget $w dcWidget instance + */ + public static function publicSource($w) + { + global $core; + + if ($w->offline) + return; + + if (!$core->blog->settings->zoneclearFeedServer->zoneclearFeedServer_active + || $w->homeonly == 1 && $core->url->type != 'default' + || $w->homeonly == 2 && $core->url->type == 'default' + ) { + return null; + } + + $p = array(); + $p['order'] = ($w->sortby && in_array($w->sortby, array('feed_upd_last', 'lowername', 'feed_creadt'))) ? + $w->sortby.' ' : 'feed_upd_last '; + $p['order'] .= $w->sort == 'desc' ? 'DESC' : 'ASC'; + $p['limit'] = abs((integer) $w->limit); + $p['feed_status'] = 1; + + $zc = new zoneclearFeedServer($core); + $rs = $zc->getFeeds($p); + + if ($rs->isEmpty()) { + + return null; + } + + $res = ''; + $i = 1; + while($rs->fetch()) { + $res .= + '
  • '. + ''.$rs->feed_name.''. + '
  • '; + $i++; + } + + if ($w->pagelink) { + $res .= '
  • '.__('All sources').'
  • '; + } + + $res = + ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : ''). + ''; + + return $w->renderDiv($w->content_only,'zoneclear-sources '.$w->class,'',$res); + } + + /** + * Widget for feeds info. + * + * @param dcWidget $w dcWidget instance + */ + public static function publicNumber($w) + { + global $core; + + if ($w->offline) + return; + + if (!$core->blog->settings->zoneclearFeedServer->zoneclearFeedServer_active + || $w->homeonly == 1 && $core->url->type != 'default' + || $w->homeonly == 2 && $core->url->type == 'default' + ) { + return null; + } + + $zc = new zoneclearFeedServer($core); + $content = ''; + + # Feed + if ($w->feed_show) { + $title = ($w->feed_title ? + ''.html::escapeHTML($w->feed_title).' ' : ''); + + $count = $zc->getFeeds(array(),true)->f(0); + + if ($count == 0) { + $text = sprintf(__('no sources'),$count); + } + elseif ($count == 1) { + $text = sprintf(__('one source'),$count); + } + else { + $text = sprintf(__('%d sources'),$count); + } + if ($core->blog->settings->zoneclearFeedServer->zoneclearFeedServer_pub_active) { + $text = ''.$text.''; + } + + $content .= sprintf('
  • %s%s
  • ',$title,$text); + } + + # Entry + if ($w->entry_show) { + $count = 0; + $feeds = $zc->getFeeds(); + + if (!$feeds->isEmpty()) { + while ($feeds->fetch()) { + $count += (integer) $zc->getPostsByFeed(array('feed_id' => $feeds->feed_id), true)->f(0); + } + } + $title = ($w->entry_title ? + ''.html::escapeHTML($w->entry_title).' ' : ''); + + if ($count == 0) { + $text = sprintf(__('no entries'),$count); + } + elseif ($count == 1) { + $text = sprintf(__('one entry'),$count); + } + else { + $text = sprintf(__('%d entries'),$count); + } + + $content .= sprintf('
  • %s%s
  • ',$title,$text); + } + + # Nothing to display + if (!$content) { + + return null; + } + + # Display + $res = + ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : ''). + ''; + + return $w->renderDiv($w->content_only,'zoneclear-number '.$w->class,'',$res); + } +} \ No newline at end of file diff --git a/changelog b/changelog new file mode 100644 index 0000000..20abb74 --- /dev/null +++ b/changelog @@ -0,0 +1,124 @@ +zoneclearFeedServer xxxx.xx.xx + * Not fixed disallow self blog feeds + * Added plugin muppet support (request Mathieu M.) + * Added log for errors + +zoneclearFeedServer 2015.04.25 - Pierre Van Glabeke + * modif nom dans liste des plugins + * modif html5 pour validation + +zoneclearFeedServer 2015.01.13 - Pierre Van Glabeke + * Dotclear 2.7 requis + * Fin de ligne unix + * Ajout case hors ligne pour les widgets + * Jeux de templates modifiés (mustek/currywurst) + * Modifications locales + +zoneclearFeedServer 2013.11.18 + * Require Dotclear 2.6 + * New icons 'traviata' thx @franckpaul + * Use new Actions systems for feeds and posts + +zoneclearFeedServer 2013.07.12 + * Added sort option on widget + * Fixed Dashboard counts + * Fixed Feed tags spliting + * Fixed typo + +zoneclearFeedServer 2013.07.02 + * Required Dotclear 2.5 + * Fixed admin pages titles and messages and typo + * Added Favorites icon + * Added new 'homeonly' option on widgets + * Fixed https protocol + * Added option to keep active empty feeds + * Added option to transform imported tags + +zoneclearFeedServer 1.3 - 2011-01-30 + * Fixed install on nightly build + * Fixed bug on null blog (and settings) + * Added verbose on admin side + * Added behaviors to open to others plugins (ie messenger) + * Added support of plugin soCialMe (writer part) + * Removed messenger functions (as it's to another plugin to do this) + +zoneclearFeedServer 1.2 - 2010-09-11 + * Added plugin tweakurls support (Thanks Mathieu M.) + +zoneclearFeedServer 1.1 - 2010-09-08 + * Removed old Twitter functions + * Added StatusNet small functions (Identica) + * Required plugin Tac for Twitter ability + +zoneclearFeedServer 1.0 - 2010-06-27 + * Switched to DC 2.2 (settings, tags) + * Fixed PHP 5.3 compatibility + * Added toogle menu and link to feed edition in admin post page + * Fixed redirection to original post + * Fixed typo + +zoneclearFeedServer 0.8 -2010-06-08 + * Added auto tweet new post + * Added option to import tags from feed (or not) + * Fixed filters on admin list (closes #466) + * Enhanced lockUpdate() function + +zoneclearFeedServer 0.7.2 - 2010-05-25 + * Fixed minor bugs + * Fixed DC 2.1.7 + +zoneclearFeedServer 0.7.1 - 2010-05-01 + * Fixed update order + +zoneclearFeedServer 0.7 - 2010-04-22 + * Added icon on dashboard if some feeds are disabled + * Added public page of feed description (first step) + * Added update of existing entries + * Added settings to add "aftercontent" and ajax options + * Added uninstall features + * Fixed duplicate entry (I hope so) using php flock + * Fixed feeds actions on admin + * Fixed typo (closes #441) + * Fixed user settings (closes #442) + +zoneclearFeedServer 0.6 - 2010-04-11 + * Added DC 2.2 compatibility (new setting) + * Added cron script to update feeds + * Fixed multiple bugs + * Changed admin interface + +zoneclearFeedServer 0.5.2 - 2010-04-05 + * Added option to redirect url to local/original post + * Changed db fields names (fixed pgSQL compatibility) + +zoneclearFeedServer 0.5.1 - 2010-02-16 + * Fixed php warning on admin post page + +zoneclearFeedServer 0.5 - 2010-02-08 + * Added option to change update interval by group of feeds + * Fixed order by lower name + * Fixed HTML escape on content + * Fixed typo + +zoneclearFeedServer 0.4.3 - 2010-01-02 + * Added option to update feeds from admin side + * Added behavior for more urls types for full content + +zoneclearFeedServer 0.4 - 2010-02-02 + * Added option to change posts owner + * Added option to truncate content on some templates + + +zoneclearFeedServer 0.3.1 - 2010-01-28 + * Fixed bug with getURL on classic post + +zoneclearFeedServer 0.3 - 2010-01-27 + * First lab release + * Fixed absolute URL + * Fixed unauthentication + +zoneclearFeedServer 0.2 - 2010-01-26 + * First release + +zoneclearFeedServer 0.1 - 2010-01-25 + * First test \ No newline at end of file diff --git a/cron-script.php b/cron-script.php new file mode 100644 index 0000000..dceeab3 --- /dev/null +++ b/cron-script.php @@ -0,0 +1,105 @@ +#!/usr/bin/env php +setBlog(DC_BLOG_ID); +if ($core->blog->id == null) { + fwrite(STDERR,"Blog is not defined\n"); + exit(1); +} + +if (!isset($opts['u']) || !$core->auth->checkUser($opts['u'])) { + fwrite(STDERR,"Unable to set user\n"); + exit(1); +} + +$core->plugins->loadModules(DC_PLUGINS_ROOT); + +$core->blog->settings->addNamespace('zoneclearFeedServer'); + +try { + $zc = new zoneclearFeedServer($core); + $zc->checkFeedsUpdate(); +} catch (Exception $e) { + fwrite(STDERR,$e->getMessage()."\n"); + exit(1); +} \ No newline at end of file diff --git a/default-templates/currywurst/zcfeeds.html b/default-templates/currywurst/zcfeeds.html new file mode 100644 index 0000000..a82f71e --- /dev/null +++ b/default-templates/currywurst/zcfeeds.html @@ -0,0 +1,68 @@ +{{tpl:extends parent="__layout.html"}} + + + {{tpl:lang List of feeds}} - {{tpl:BlogName encode_html="1"}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    +

    {{tpl:lang List of feeds}}

    +

    {{tpl:zcFeedsCount}} - {{tpl:zcFeedsEntriesCount}}

    +
    +
    + +
    + +

    {{tpl:zcFeedName encode_html="1"}}

    + + + +
    {{tpl:zcFeedDesc}}
    + +
    +
    + + \ No newline at end of file diff --git a/default-templates/mustek/zcfeeds.html b/default-templates/mustek/zcfeeds.html new file mode 100644 index 0000000..25c1d5a --- /dev/null +++ b/default-templates/mustek/zcfeeds.html @@ -0,0 +1,87 @@ + + + + + + + {{tpl:lang List of feeds}} - {{tpl:BlogName encode_html="1"}} + + + + + + + + + + + + + + + + + + + + + + + + + {{tpl:include src="_head.html"}} + + + +
    + +{{tpl:include src="_top.html"}} + +
    + +
    +
    + + + +
    +

    {{tpl:lang List of feeds}}

    +

    {{tpl:zcFeedsCount}} - {{tpl:zcFeedsEntriesCount}}

    +
    +
    +
    + +

    {{tpl:zcFeedName encode_html="1"}}

    + + + +
    {{tpl:zcFeedDesc}}
    + +
    +
    +
    +
    + + + +
    + +{{tpl:include src="_footer.html"}} +
    + + \ No newline at end of file diff --git a/default-templates/zcfsupd.js b/default-templates/zcfsupd.js new file mode 100644 index 0000000..b13df2d --- /dev/null +++ b/default-templates/zcfsupd.js @@ -0,0 +1,32 @@ +/* -- BEGIN LICENSE BLOCK ---------------------------------- + * + * This file is part of zoneclearFeedServer, a plugin for Dotclear 2. + * + * Copyright (c) 2009-2015 Jean-Christian Denis, BG and contributors + * + * Licensed under the GPL version 2.0 license. + * A copy of this license is available in LICENSE file or at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * + * -- END LICENSE BLOCK ------------------------------------*/ + +;if(window.jQuery) (function($) { + + $.fn.zoneclearFeedServer = function(options) { + var opts = $.extend({}, $.fn.zoneclearFeedServer.defaults, options); + return this.each(function() { + $.ajax({ + timeout:5000, + url:opts.blog_url, + type:'POST', + data:{blogId:opts.blog_id}/*, + error:function(){alert('Feeds update failed');}, + succes:function(data){data=$(data);alert($(data).find('message').text());}*/ + }); + }); + }; + $.fn.zoneclearFeedServer.defaults = { + blog_url: '', + blog_id: '' + }; +})(jQuery); \ No newline at end of file diff --git a/icon-big-update.png b/icon-big-update.png new file mode 100644 index 0000000000000000000000000000000000000000..97d59c1bdf36b0dda1875e3cc2ca346b10d2e1bc GIT binary patch literal 1580 zcmV+{2GjY8P)<*{v1ktZ$+015z4T+|W#Zj%%Mh>6515Y-v5wzgJbu~=R^ozCYEd0(wo`)@-- z!+2?F>9nK)Fqur>!0_hQXgUXAct1}_NFW-GhS=?PAH9r>4B~RR$l2K$+i9;p9+Q)k z&kG6){)T(FCEo+kc!R+}&j$wwy&$x;wNYoyW;0n>SfF!NRaK;^sfmIzG&B@YUpA{i ze0==9=fUVaWc0(D0qkh9(|u%QghqF3Ys))_nSj@@qwG&#R?8rt;Y>Yqg$+m`eT4|g zBm;)z0)Rq z+z7MpA?AKz&j72{>LoZ_@-jR;OtWKYY3WYwGEQ(mL$=7LgJfxJY>YC=<>h7R0KixK z?2MS6=6{0aIw(Yk+Y=NfDCK7Xf8z0Yh{NHaBQ-*;COVytj!_N3!NCE!zP={M$H#X* z!?~1{6rxh8NP2pD^Z`cXyNR?QKC|vP%R@C@U*VIsl+y zxSr$4m*QB@$Q04>q@*M|cXDz<($dld0l-%xo12>y4BRRUwM5iGHnW_?#l@H4Kmpb_ zSI|+6GCH1{o9mrNhbQ0s-TD2*Rfa0RUfg%+Ag>qtgJw7knv>4&#Ao z%?LUTdUSkj0q6fjFuH8wy8Zf7+}8*vw~eBK2309 zV&ZFv_$xkbOm(Bt=#%2m56H~Sj9h4c4Ft9ZD0l_}z*_=X?|prJzwkvLrM0z{HZ^oS z%ndDUS&rv)TMt zYHBJq8lx3RE-o&pGt9d`M#Sn@R8&+ZCMJ4+I32A0F;=VfN&iw(`L8hr00jUA00jUA efF~^f2`~Unv_m%h>x}sT0000 literal 0 HcmV?d00001 diff --git a/icon-big.png b/icon-big.png new file mode 100644 index 0000000000000000000000000000000000000000..aef2e1b2eed8985660740efb0a272c5149bf624a GIT binary patch literal 1637 zcmV-r2AcVaP);wY7a;I03*C+LCkhaAQ~$z^wRTw4hdokkkNNr`45u z=;9^`D1!A~x~`ZcgGlqd=r=Wgp~l0 zAb}p8x^}}7$DFkG^hxTR1rxt*II=j7pU*Z_QP*7Jup^|KA5a;KOnlaSKaoKm)Hg)N zGRTa?jLpIOo)4b|LW^tsJT?}<|+6QXVF=wyv!#Ay(A z&U<~QKj!tpX32c+QxXr|B-ckSf^sJqf!_suen*InBj2YzM>^m@D<6G8%HT-!dZL?v z+sT_qM|vK0W?G}7gfyy4NXf(_Qto_6ouh_;K}9+hX^c2V-XB4Dpb}6KsEnLxr}PN0 z$0f~28$crgfuzXwi~{OF0+0w)h05cKYyvRKT`8I+5~oeCRgvoFv#9f{SGvf(;m3j$ z#7q(0xP?+j#1McJY=uZ6Xg-N+(iG(Fmo)%fO;Y0LA2;rvC7M))AOiSOgeIeMnH~B|-~Ms}^xvNkS`BjBq)TZpOOPLU7_gS5E+&i)tb z^;)F~$hNE)0WjfIn7F>(?5HrA?f5MwoloNWd?l&gp?=aOj!gq#2L&96TgiIngy)+o zw90lM-vmJz3kd-?2S;}`_gG&?@Ib<5K8Yh>1LSr#$eK1Fi8S9Grp~Kv0R9go0p|7f z&YZNLL=%7#2hi2cJ;MgP=0=;AI0Ax>w$Rr-DDljdocVro1uFZTYvPb|e zaf~)boloKj)&Rw<0;J9?Xb2dAi!ExaO$Mp~Rl!UV76E&%blrf67x8(c)bF0$#gaJG z17Za5QZm5Nd!tsjX9)pxzVEx%-NF}rw6ppx!~#VPfv<2uTQL>zr z^h6PWozp_@NG=sHaK7?hFab1+ct|eq4;Ix3`9dUUR~VVZN-7obb!D3`2(4f11j=a) z>wy$f0fE<*b1 z`=AJjv@S7_ycbNsz=%5!k3hS`mo(|r5vU39UpDWTn?G$n|1My*P33nFxr*`Heny$_6|yOm1KY6{O+*gsaVoE;1C5~fd8_2?{EG-_XCE;W;ABo^j6zr z&ol7y^M&D>%#Cq>Ycm!1vr{*)HWrZpliB_z{kkwKh3wAFAbA-{touG3agiSfMo8cA z__Dx-`UCLRmLtVWexW9I{xQ9Oxu`wB(W%)~bnGNThqUkl>ci?CO{@Y jCO{@YCSVQQ{{jpEoe&gswYV>f00000NkvXXu0mjfBJmIX literal 0 HcmV?d00001 diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..05461dbcdf2785968307bc40296ab93960a85e0b GIT binary patch literal 411 zcmV;M0c8G(P)FrwLT)GrcEh4rT8RI&kRwvdGhkn!%s8B7M;9uyn+b+m-dK`MYGoBzcfs = new zoneclearFeedServer($core); + + parent::__construct($core, $uri, $redirect_args); + $this->redirect_fields = array( + 'sortby', 'order', 'page', 'nb' + ); + $this->field_entries = 'feeds'; + $this->caller_title = __('Feeds'); + $this->loadDefaults(); + } + + protected function loadDefaults() + { + zcfsDefaultFeedsActions::zcfsFeedsActionsPage($this->core, $this); + $this->core->callBehavior('zcfsFeedsActionsPage', $this->core, $this); + } + + public function beginPage($breadcrumb='', $head='') + { + echo + ''.__('Feeds server').''. + dcPage::jsLoad('js/_posts_actions.js'). + $head. + ''. + $breadcrumb. + '

    '. + __('Back to feeds list').'

    '; + } + + public function endPage() + { + echo + ''; + } + + public function error(Exception $e) + { + $this->core->error->add($e->getMessage()); + $this->beginPage(dcPage::breadcrumb(array( + html::escapeHTML($this->core->blog->name) => '', + $this->getCallerTitle() => $this->getRedirection(true), + __('Feeds actions') => '' + ))); + $this->endPage(); + } + + protected function fetchEntries($from) + { + if (!empty($from['feeds'])) { + + $params['feed_id'] = $from['feeds']; + + $feeds = $this->zcfs->getFeeds($params); + while ($feeds->fetch()) { + $this->entries[$feeds->feed_id] = $feeds->feed_name; + } + $this->rs = $feeds; + } + else { + $this->rs = $this->core->con->select( + "SELECT blog_id FROM ". + $this->core->prefix."blog 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 zcfsFeedsActionsPage(dcCore $core, zcfsFeedsActionsPage $ap) + { + $ap->addAction( + array(__('Change category') => 'changecat'), + array('zcfsDefaultFeedsActions', 'doChangeCategory') + ); + $ap->addAction( + array(__('Change update interval') => 'changeint'), + array('zcfsDefaultFeedsActions', 'doChangeInterval') + ); + $ap->addAction( + array(__('Disable feed update') => 'disablefeed'), + array('zcfsDefaultFeedsActions', 'doEnableFeed') + ); + $ap->addAction( + array(__('Enable feed update') => 'enablefeed'), + array('zcfsDefaultFeedsActions', 'doEnableFeed') + ); + $ap->addAction( + array(__('Reset last update') => 'resetupdlast'), + array('zcfsDefaultFeedsActions', 'doResetUpdate') + ); + $ap->addAction( + array(__('Update (check) feed') => 'updatefeed'), + array('zcfsDefaultFeedsActions', 'doUpdateFeed') + ); + $ap->addAction( + array(__('Delete related posts') => 'deletepost'), + array('zcfsDefaultFeedsActions', 'doDeletePost') + ); + $ap->addAction( + array(__('Delete feed (without related posts)') => 'deletefeed'), + array('zcfsDefaultFeedsActions', 'doDeleteFeed') + ); + } + + public static function doEnableFeed(dcCore $core, zcfsFeedsActionsPage $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); + } + + dcPage::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(dcCore $core, zcfsFeedsActionsPage $ap, $post) + { + $types = array( + '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(array( + 'feed_id' => $id + )); + + while($posts->fetch()) { + + $core->blog->delPost($posts->post_id); + $core->con->execute( + 'DELETE FROM '.$core->prefix.'meta '. + 'WHERE post_id = '.$posts->post_id.' '. + 'AND meta_type '.$core->con->in($types).' ' + ); + } + } + + dcPage::addSuccessNotice( + __('Entries have been successfully deleted.') + ); + $ap->redirect(true); + } + + public static function doDeleteFeed(dcCore $core, zcfsFeedsActionsPage $ap, $post) + { + $ids = $ap->getIDs(); + + if (empty($ids)) { + throw new Exception(__('No feeds selected')); + } + + foreach($ids as $id) { + $ap->zcfs->delFeed($id); + } + + dcPage::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(dcCore $core, zcfsFeedsActionsPage $ap, $post) + { + $ids = $ap->getIDs(); + + if (empty($ids)) { + throw new Exception(__('No feeds selected')); + } + + foreach($ids as $id) { + $ap->zcfs->checkFeedsUpdate($id, true); + } + + 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(dcCore $core, zcfsFeedsActionsPage $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); + } + + 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(dcCore $core, zcfsFeedsActionsPage $ap, $post) + { + if (isset($post['upd_cat_id'])) { + $ids = $ap->getIDs(); + + if (empty($ids)) { + throw new Exception(__('No feeds selected')); + } + + $cat_id = abs((integer) $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); + } + + 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( + $core->blog->getCategories() + ); + + $ap->beginPage( + dcPage::breadcrumb( + array( + html::escapeHTML($core->blog->name) => '', + __('Feeds server') => '', + $ap->getCallerTitle() => $ap->getRedirection(true), + __('Change category for this selection') => '' + ))); + + echo + '
    '. + $ap->getCheckboxes(). + '

    '. + form::combo(array('upd_cat_id'), $categories_combo, ''). + $core->formNonce(). + $ap->getHiddenFields(). + form::hidden(array('action'), 'changecat'). + '

    '. + '
    '; + + $ap->endPage(); + } + } + + public static function doChangeInterval(dcCore $core, zcfsFeedsActionsPage $ap, $post) + { + if (isset($post['upd_upd_int'])) { + $ids = $ap->getIDs(); + + if (empty($ids)) { + throw new Exception(__('No feeds selected')); + } + + $upd_int = abs((integer) $post['upd_upd_int']); + + foreach($ids as $id) { + $cur = $ap->zcfs->openCursor(); + $cur->feed_upd_int = $upd_int; + $ap->zcfs->updFeed($id, $cur); + } + + dcPage::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( + array( + html::escapeHTML($core->blog->name) => '', + __('Feeds server') => '', + $ap->getCallerTitle() => $ap->getRedirection(true), + __('Change update frequency for this selection') => '' + ))); + + echo + '
    '. + $ap->getCheckboxes(). + '

    '. + form::combo(array('upd_upd_int'), $ap->zcfs->getAllUpdateInterval(), ''). + $core->formNonce(). + $ap->getHiddenFields(). + form::hidden(array('action'), 'changeint'). + '

    '. + '
    '; + + $ap->endPage(); + } + } +} \ No newline at end of file diff --git a/inc/class.zoneclear.feed.server.php b/inc/class.zoneclear.feed.server.php new file mode 100644 index 0000000..2a097c3 --- /dev/null +++ b/inc/class.zoneclear.feed.server.php @@ -0,0 +1,933 @@ +core = $core; + $this->con = $core->con; + $this->blog = $core->con->escape($core->blog->id); + $this->table = $core->prefix.'zc_feed'; + } + + /** + * 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 = (integer) $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 + $this->core->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 + $this->core->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 = (integer) $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 = (integer) $enable; + if (null !== $time) { + $cur->feed_upd_last = (integer) $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 + $this->core->callBehavior( + 'zoneclearFeedServerAfterEnableFeed', + $id, + $enable, + $time + ); + } + + # + /** + * Delete record (this not deletes post). + * + * @param integer $id Feed Id + */ + public function delFeed($id) + { + $id = (integer) $id; + + if ($id < 1) { + throw new Exception(__('No such ID')); + } + + # --BEHAVIOR-- zoneclearFeedServerBeforeDelFeed + $this->core->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 record record instance + */ + public function getPostsByFeed($params=array(), $count_only=false) + { + if (!isset($params['feed_id'])) { + + return null; + } + + $params['from'] = + 'LEFT JOIN '.$this->core->prefix.'meta F '. + 'ON P.post_id = F.post_id '; + $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 $this->core->blog->getPosts($params, $count_only); + } + + /** + * Get feed record. + * + * @param array $params Query params + * @param boolean $count_only Return only result count + * @return record record instance + */ + public function getFeeds($params=array(), $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 '.$this->core->prefix.'category 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'],create_function('&$v,$k','if($v!==null){$v=(integer)$v;}')); + } + else { + $params['feed_id'] = array((integer) $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 = ".((integer) $params['feed_status'])." "; + } + + 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); + $rs->zc = $this; + + return $rs; + } + + /** + * Get next table id. + * + * @return record record instance + */ + 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) + { + # Limit to one update at a time + try { + $this->lockUpdate(); + } + catch (Exception $e) { + if ($throw) { + throw $e; + } + + return false; + } + + dt::setTZ($this->core->blog->settings->system->blog_timezone); + $time = time(); + $s = $this->core->blog->settings->zoneclearFeedServer; + + # All feeds or only one (from admin) + $f = !$id ? + $this->getFeeds(array( + 'feed_status'=>1, + 'order'=>'feed_upd_last ASC' + )) : + $this->getFeeds(array( + 'feed_id'=>$id + )); + + # No feed + if ($f->isEmpty()) { + + return false; + } + + # Set feeds user + $this->enableUser($s->zoneclearFeedServer_user); + + $updates = false; + $loop_mem = array(); + + $limit = abs((integer) $s->zoneclearFeedServer_update_limit); + if ($limit < 1) { + $limit = 10; + } + $i = 0; + + $cur_post = $this->con->openCursor($this->core->prefix.'post'); + $cur_meta = $this->con->openCursor($this->core->prefix.'meta'); + + 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 + ) { + $i++; + $feed = self::readFeed($f->feed_feed); + + # Nothing to parse + if (!$feed) { + # Keep active empty feed or disable it ? + if (!$s->zoneclearFeedServer_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 '.$this->core->prefix.'post P '. + 'INNER JOIN '.$this->core->prefix.'meta 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_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 = $this->core->auth->userID(); + $cur_post->post_format = 'xhtml'; + $cur_post->post_status = (integer) $s->zoneclearFeedServer_post_status_new; + $cur_post->post_open_comment = 0; + $cur_post->post_open_tb = 0; + + # --BEHAVIOR-- zoneclearFeedServerBeforePostCreate + $this->core->callBehavior( + 'zoneclearFeedServerBeforePostCreate', + $cur_post + ); + + $post_id = $this->core->auth->sudo( + array($this->core->blog, 'addPost'), + $cur_post + ); + + # --BEHAVIOR-- zoneclearFeedServerAfterPostCreate + $this->core->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 + $this->core->callBehavior( + 'zoneclearFeedServerBeforePostUpdate', + $cur_post, + $post_id + ); + + $this->core->auth->sudo( + array($this->core->blog, 'updPost'), + $post_id, + $cur_post + ); + + # Quick delete old meta + $this->con->execute( + 'DELETE FROM '.$this->core->prefix.'meta '. + 'WHERE post_id = '.$post_id.' '. + "AND meta_type LIKE 'zoneclearfeed_%' " + ); + # Delete old tags + $this->core->auth->sudo( + array($this->core->meta, 'delPostMeta'), + $post_id, + 'tag' + ); + + # --BEHAVIOR-- zoneclearFeedServerAfterPostUpdate + $this->core->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 = $this->core->meta->splitMetaValues($f->feed_tags); + if ($f->feed_get_tags) { + + # Some feed subjects contains more than one tag + foreach($item->subject as $subjects) { + $tmp = $this->core->meta->splitMetaValues($subjects); + $tags = array_merge($tags, $tmp); + } + $tags = array_unique($tags); + } + $formated_tags = array(); + foreach ($tags as $tag) { + + # Change tags case + switch((integer) $s->zoneclearFeedServer_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; + $this->core->auth->sudo( + array($this->core->meta, 'setPostMeta'), + $post_id, + 'tag', + dcMeta::sanitizeMetaID($tag) + ); + } + } + $meta->tags = $formated_tags; + + # --BEHAVIOR-- zoneclearFeedServerAfterFeedUpdate + $this->core->callBehavior( + 'zoneclearFeedServerAfterFeedUpdate', + $this->core, + $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(); + } + } + } + $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) { + if (!$this->core->auth->checkUser($enable)) { + throw new Exception('Unable to set user'); + } + } + # Disable + else { + $this->core->auth = null; + $this->core->auth = new dcAuth($this->core); + } + } + + /** + * Read and parse external feeds. + * + * @param string $f Feed URL + * @return arrayObject 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 null; + } + } + + /** + * Trigger. + */ + private function trigger() + { + $this->core->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 array( + __('Disabled') => '0', + __('Enabled') => '1' + ); + } + + /** + * Get list of predefined interval. + * + * @return array List of Name/time of intervals + */ + public static function getAllUpdateInterval() + { + return array( + __('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 = array(); + + # Get super admins + $rs = $this->con->select( + 'SELECT user_id, user_super, user_name, user_firstname, user_displayname '. + 'FROM '.$this->con->escapeSystem($this->core->prefix.'user').' '. + '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($this->core->prefix.'user').' U '. + 'LEFT JOIN '.$this->con->escapeSystem($this->core->prefix.'permissions').' 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. + * + * @param dcCore $core dcCore instance + * @return array List of names/types of URLs + */ + public static function getPublicUrlTypes(dcCore $core) + { + $types = array(); + + # --BEHAVIOR-- zoneclearFeedServerPublicUrlTypes + $core->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) + { + global $core; + $cur->post_url = tweakUrls::tweakBlogURL($cur->post_url); + $core->auth->sudo(array($core->blog, 'updPost'), $id, $cur); + } +} \ No newline at end of file diff --git a/inc/lib.zcfs.list.php b/inc/lib.zcfs.list.php new file mode 100644 index 0000000..011a90d --- /dev/null +++ b/inc/lib.zcfs.list.php @@ -0,0 +1,204 @@ +rs->isEmpty()) { + + return '

    '.__('There is no feed').'

    '; + } + + $pager = new dcPager($page, $this->rs_count ,$nb_per_page, 10); + + $pager->base_url = $url; + + $html_block = + '
    '. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + '%s'. + '
    '.__('Name').''.__('Feed').''.__('Frequency').''.__('Last update').''.__('Entries').''.__('Status').'
    '. + '
    '; + + $res = ''; + while ($this->rs->fetch()) { + $res .= $this->feedsLine(); + } + + return + $pager->getLinks(). + sprintf($enclose, sprintf($html_block, $res)). + $pager->getLinks(); + } + + private function feedsLine() + { + $combo_status = zoneclearFeedServer::getAllStatus(); + $combo_upd_int = zoneclearFeedServer::getAllUpdateInterval(); + $status = $this->rs->feed_status ? + 'enable' : + 'disable'; + $category = $this->rs->cat_id ? + $this->rs->cat_title : __('no categories'); + + $entries_count = $this->rs->zc->getPostsByFeed(array('feed_id' => $this->rs->feed_id), true)->f(0); + $shunk_feed = $this->rs->feed_feed; + if (strlen($shunk_feed) > 83) { + $shunk_feed = substr($shunk_feed,0,50).'...'.substr($shunk_feed,-20); + } + + $url = 'plugin.php?p=zoneclearFeedServer&part=feed&feed_id='.$this->rs->feed_id; + + return + ''."\n". + ''. + form::checkbox(array('feeds[]'), $this->rs->feed_id, 0). + ''. + ''. + ''. + html::escapeHTML($this->rs->feed_name).''. + "\n". + ''. + ''.html::escapeHTML($shunk_feed).''. + "\n". + ''. + array_search($this->rs->feed_upd_int,$combo_upd_int). + "\n". + ''. + ($this->rs->feed_upd_last < 1 ? + __('never') : + dt::str(__('%Y-%m-%d %H:%M'), $this->rs->feed_upd_last,$this->rs->zc->core->auth->getInfo('user_tz')) + ). + "\n". + ''. + ($entries_count ? + ''.$entries_count.'' : + $entries_count + ). + "\n". + ''. + $status. + "\n". + ''."\n"; + } +} + +/** + * @ingroup DC_PLUGIN_ZONECLEARFEEDSERVER + * @brief Feeds server - Posts list methods + * @since 2.6 + * @see adminGenericList for more info + */ +class zcfsEntriesList extends adminGenericList +{ + public function display($page, $nb_per_page, $url, $enclose='') + { + if ($this->rs->isEmpty()) { + + return '

    '.__('No entry').'

    '; + } + + $pager = new dcPager($page, $this->rs_count, $nb_per_page, 10); + $pager->base_url = $url; + $pager->html_prev = $this->html_prev; + $pager->html_next = $this->html_next; + $pager->var_page = 'page'; + + $html_block = + '
    '. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + '%s
    '.__('Title').''.__('Date').''.__('Category').''.__('Author').''.__('Comments').''.__('Trackbacks').''.__('Status').'
    '; + + $res = ''; + while ($this->rs->fetch()) { + $res .= $this->postLine(); + } + + return + $pager->getLinks(). + sprintf($enclose, sprintf($html_block, $res)). + $pager->getLinks(); + } + + private function postLine() + { + $cat_link = $this->core->auth->check('categories', $this->core->blog->id) ? + '%s' + : '%2$s'; + + $cat_title = $this->rs->cat_title ? + sprintf($cat_link,$this->rs->cat_id, html::escapeHTML($this->rs->cat_title)) + : __('None'); + + $img = '%1$s'; + switch ($this->rs->post_status) { + case 1: + $img_status = sprintf($img, __('published'), 'check-on.png'); + break; + case 0: + $img_status = sprintf($img, __('unpublished'), 'check-off.png'); + break; + case -1: + $img_status = sprintf($img, __('scheduled'), 'scheduled.png'); + break; + case -2: + $img_status = sprintf($img, __('pending'), 'check-wrn.png'); + break; + } + + return + ''. + ''. + form::checkbox(array('entries[]'), $this->rs->post_id, '', '', '', !$this->rs->isEditable()).''. + ''. + html::escapeHTML($this->rs->post_title).''. + ''.dt::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->post_dt).''. + ''.$cat_title.''. + ''.$this->rs->user_id.''. + ''.$this->rs->nb_comment.''. + ''.$this->rs->nb_trackback.''. + ''.$img_status.''. + ''; + } +} \ No newline at end of file diff --git a/inc/lib.zcfs.socialmewriter.php b/inc/lib.zcfs.socialmewriter.php new file mode 100644 index 0000000..9b206db --- /dev/null +++ b/inc/lib.zcfs.socialmewriter.php @@ -0,0 +1,148 @@ + __('New Zoneclear post'), + 'description' => __('When a feed has new entry'), + 'action' => array('Message','Link'), + 'format' => array('Message'), + 'wildcards' => array('Message' => array( + '%posttitle%', + '%postlink%', + '%postauthor%', + '%posttweeter%', + '%sitetitle%', + '%sitelink%', + '%tags' + )) + ); + } + + public static function zoneclearFeedServerAfterFeedUpdate($core, $is_new_published_entry, $post, $meta) + { + // for now only new post + if(!$is_new_published_entry) { + + return null; + } + + $key = 'zcfscreate'; + + # Is install + if (!$core->plugins->moduleExists('soCialMe')) { + + return null; + } + + # Is active + if (!$core->blog->settings->soCialMeWriter->active) { + + return null; + } + + # Load services + $soCialMeWriter = new soCialMeWriter($core); + + # List of service per action + $actions = $soCialMeWriter->getMarker('action'); + + # List of format per type + $formats = $soCialMeWriter->getMarker('format'); + + # prepare data + $shortposturl = soCialMeUtils::reduceURL($meta->url); + $shortposturl = $shortposturl ? $shortposturl : $meta->url; + + $shortsiteurl = soCialMeUtils::reduceURL($meta->site); + $shortsiteurl = $shortsiteurl ? $shortsiteurl : $meta->site; + + // need this? + foreach($meta->tags as $k => $tag) { + $tags[$k] = '#'.$tag; + } + + # sendMessage + if (!empty($formats[$key]['Message']) + && !empty($actions[$key]['Message']) + ) { + // parse message + $message_txt = str_replace( + array( + '%posttitle%', + '%postlink%', + '%postauthor%', + '%posttweeter%', + '%sitetitle%', + '%sitelink%', + '%tags' + ), + array( + $post->post_title, + $shortposturl, + $meta->author, + $meta->tweeter, + $meta->sitename, + $shortsiteurl, + implode(',', $meta->tags) + ), + $formats[$key]['Message'] + ); + + // send message + if (!empty($message_txt)) { + foreach($actions[$key]['Message'] as $service_id) { + $soCialMeWriter->play( + $service_id, + 'Message', + 'Content', + $message_txt + ); + } + } + } + + # sendLink + if (!empty($actions[$key]['Link'])) { + foreach($actions[$key]['Link'] as $service_id) { + $soCialMeWriter->play( + $service_id, + 'Link', + 'Content', + $cur->post_title,$shortposturl + ); + } + } + + # sendData + // not yet implemented + + #sendArticle + // not yet implemented + } +} \ No newline at end of file diff --git a/inc/lib.zcfsr.activityreport.php b/inc/lib.zcfsr.activityreport.php new file mode 100644 index 0000000..b6a76f5 --- /dev/null +++ b/inc/lib.zcfsr.activityreport.php @@ -0,0 +1,169 @@ +activityReport->addGroup( + 'zoneclearFeedServer', + __('Plugin zoneclearFeedServer') +); + +# from BEHAVIOR zoneclearFeedServerAfterAddFeed in zoneclearFeedServer/inc/class.zoneclear.feed.server.php +$core->activityReport->addAction( + 'zoneclearFeedServer', + 'create', + __('feed creation'), + __('A new feed named "%s" point to "%s" was added by "%s"'), + 'zoneclearFeedServerAfterAddFeed', + array('zoneclearFeedServerActivityReportBehaviors', 'addFeed') +); +# from BEHAVIOR zoneclearFeedServerAfterUpdFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php +$core->activityReport->addAction( + 'zoneclearFeedServer', + 'updatefeedinfo', + __('updating feed info'), + __('Feed named "%s" point to "%s" has been updated by "%s"'), + 'zoneclearFeedServerAfterUpdFeed', + array('zoneclearFeedServerActivityReportBehaviors', 'updFeedInfo') +); +# from BEHAVIOR zoneclearFeedServerAfterUpdFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php +$core->activityReport->addAction( + 'zoneclearFeedServer', + 'updatefeedrecords', + __('updating feed records'), + __('Records of the feed named "%s" have been updated automatically'), + 'zoneclearFeedServerAfterUpdFeed', + array('zoneclearFeedServerActivityReportBehaviors', 'updFeedRecord') +); +# from BEHAVIOR zoneclearFeedServerAfterDelFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php +$core->activityReport->addAction( + 'zoneclearFeedServer', + 'delete', + __('feed deletion'), + __('Feed named "%s" point to "%s" has been deleted by "%s"'), + 'zoneclearFeedServerAfterDelFeed', + array('zoneclearFeedServerActivityReportBehaviors', 'delFeed') +); +# from BEHAVIOR zoneclearFeedServerAfterEnableFeed in in zoneclearFeedServer/inc/class.zoneclear.feed.server.php +$core->activityReport->addAction( + 'zoneclearFeedServer', + 'status', + __('feed status'), + __('Feed named "%s" point to "%s" has been set to "%s"'), + 'zoneclearFeedServerAfterEnableFeed', + array('zoneclearFeedServerActivityReportBehaviors', 'enableFeed') +); + +class zoneclearFeedServerActivityReportBehaviors +{ + public static function addFeed($cur) + { + global $core; + + $logs = array( + $cur->feed_name, + $cur->feed_feed, + $core->auth->getInfo('user_cn') + ); + + $core->activityReport->addLog( + 'zoneclearFeedServer', + 'create', + $logs + ); + } + + public static function updFeedInfo($cur, $id) + { + if (defined('DC_CONTEXT_ADMIN')) { + global $core; + $zc = new zoneclearFeedServer($core); + $rs = $zc->getFeeds(array('feed_id' => $id)); + + $logs = array( + $rs->feed_name, + $rs->feed_feed, + $core->auth->getInfo('user_cn') + ); + + $core->activityReport->addLog( + 'zoneclearFeedServer', + 'updatefeedinfo', + $logs + ); + } + } + + public static function updFeedRecord($cur,$id) + { + if (!defined('DC_CONTEXT_ADMIN')) { + global $core; + $zc = new zoneclearFeedServer($core); + $rs = $zc->getFeeds(array('feed_id' => $id)); + + $logs = array( + $rs->feed_name + ); + + $core->activityReport->addLog( + 'zoneclearFeedServer', + 'updatefeedrecords', + $logs + ); + } + } + + public static function delFeed($id) + { + global $core; + + $zc = new zoneclearFeedServer($core); + $rs = $zc->getFeeds(array('feed_id' => $id)); + + $logs = array( + $rs->feed_name, + $rs->feed_feed, + $core->auth->getInfo('user_cn') + ); + + $core->activityReport->addLog( + 'zoneclearFeedServer', + 'delete', + $logs + ); + } + + public static function enableFeed($id, $enable, $time) + { + global $core; + + $zc = new zoneclearFeedServer($core); + $rs = $zc->getFeeds(array('feed_id' => $id)); + + $logs = array( + $rs->feed_name, + $rs->feed_feed, + $enable ? 'enable' : 'disable' + ); + + $core->activityReport->addLog( + 'zoneclearFeedServer', + 'status', + $logs + ); + } +} \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..4b3f838 --- /dev/null +++ b/index.php @@ -0,0 +1,856 @@ +getVersion('zoneclearFeedServer') != + $core->plugins->moduleInfo('zoneclearFeedServer', 'version')) { + + return null; +} + +dcPage::check('admin'); + +$zcfs = new zoneclearFeedServer($core); + +############################################################ +# +# One feed +# +############################################################ + +if (isset($_REQUEST['part']) && $_REQUEST['part'] == 'feed') { + + $feed_id = ''; + $feed_name = ''; + $feed_desc = ''; + $feed_owner = ''; + $feed_tweeter = ''; + $feed_url = ''; + $feed_feed = ''; + $feed_lang = $core->auth->getInfo('user_lang'); + $feed_tags = ''; + $feed_get_tags = '0'; + $feed_cat_id = ''; + $feed_status = '0'; + $feed_upd_int = 3600; + + $can_view_page = true; + + $feed_headlink = ''; + $feed_link = '%s'; + + $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 = array('-' => ''); + try { + $categories = $core->blog->getCategories(array( + 'post_type' => 'post' + )); + while ($categories->fetch()) { + $combo_categories[ + str_repeat('  ', $categories->level-1). + '• '.html::escapeHTML($categories->cat_title) + ] = $categories->cat_id; + } + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } + + # Get entry informations + if (!empty($_REQUEST['feed_id'])) { + $feed = $zcfs->getFeeds(array('feed_id' => $_REQUEST['feed_id'])); + + if ($feed->isEmpty()) { + $core->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 = array( + 'sql' => 'AND feed_id < '.$feed_id.' ', + 'limit' => 1 + ); + $next_rs = $zcfs->getFeeds($next_params); + $prev_params = array( + '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); + } + + 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']; + if (isset($_POST['feed_status'])) { + $feed_status = (integer) $_POST['feed_status']; + } + $feed_upd_int = $_POST['feed_upd_int']; + + $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.')); + } + $get_feed_cat_id = $core->blog->getCategory($feed_cat_id); + if ($feed_cat_id != '' && !$get_feed_cat_id) { + throw new Exception(__('You must provide valid category.')); + } + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } + } + + if (!empty($_POST['action']) && $_POST['action'] == 'savefeed' + && !$core->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 = (integer) $feed_get_tags; + $cur->cat_id = $feed_cat_id != '' ? (integer) $feed_cat_id : null; + $cur->feed_status = (integer) $feed_status; + $cur->feed_upd_int = (integer) $feed_upd_int; + + # Update feed + if ($feed_id) { + try { + # --BEHAVIOR-- adminBeforeZoneclearFeedServerFeedUpdate + $core->callBehavior( + 'adminBeforeZoneclearFeedServerFeedUpdate', + $cur, + $feed_id + ); + + $zcfs->updFeed($feed_id, $cur); + + # --BEHAVIOR-- adminAfterZoneclearFeedServerFeedUpdate + $core->callBehavior( + 'adminAfterZoneclearFeedServerFeedUpdate', + $cur, + $feed_id + ); + + dcPage::addSuccessNotice( + __('Feed successfully updated.') + ); + http::redirect( + $p_url.'&part=feed&feed_id='.$feed_id + ); + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } + } + else { + try { + # --BEHAVIOR-- adminBeforeZoneclearFeedServerFeedCreate + $core->callBehavior( + 'adminBeforeZoneclearFeedServerFeedCreate', + $cur + ); + + $return_id = $zcfs->addFeed($cur); + + # --BEHAVIOR-- adminAfterZoneclearFeedServerFeedCreate + $core->callBehavior( + 'adminAfterZoneclearFeedServerFeedCreate', + $cur, + $return_id + ); + + dcPage::addSuccessNotice( + __('Feed successfully created.') + ); + http::redirect( + $p_url.'&part=feed&feed_id='.$return_id + ); + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } + } + } + + # Prepared entries list + if ($feed_id && $can_view_page) { + try { + # Getting categories + $categories = $core->blog->getCategories(array( + 'post_type' => 'post' + )); + + # Getting authors + $users = $core->blog->getPostsUsers(); + + # Getting dates + $dates = $core->blog->getDates(array( + 'type' => 'month' + )); + + # Getting langs + $langs = $core->blog->getLangs(); + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } + + # Creating filter combo boxes + if (!$core->error->flag()) { + + $users_combo = array_merge( + array('-' => ''), + dcAdminCombos::getUsersCombo($users) + ); + + $categories_combo = array_merge( + array( + new formSelectOption('-', ''), + new formSelectOption(__('(No cat)'), 'NULL') + ), + dcAdminCombos::getCategoriesCombo($categories, false) + ); + $categories_values = array(); + foreach ($categories_combo as $cat) { + if (isset($cat->value)) { + $categories_values[$cat->value] = true; + } + } + + $status_combo = array_merge( + array('-' => ''), + dcAdminCombos::getPostStatusesCombo() + ); + + $selected_combo = array( + '-' => '', + __('Selected') => '1', + __('Not selected') => '0' + ); + + $dt_m_combo = array_merge( + array('-' => ''), + dcAdminCombos::getDatesCombo($dates) + ); + + $lang_combo = array_merge( + array('-' => ''), + dcAdminCombos::getLangsCombo($langs,false) + ); + + $sortby_combo = array( + __('Date') => 'post_dt', + __('Title') => 'post_title', + __('Category') => 'cat_title', + __('Author') => 'user_id', + __('Status') => 'post_status', + __('Selected') => 'post_selected' + ); + + $order_combo = array( + __('Descending') => 'desc', + __('Ascending') => 'asc' + ); + } + + # Posts action + $posts_actions_page = new dcPostsActionsPage( + $core, + 'plugin.php', + array( + 'p' => 'zoneclearFeedServer', + 'part' => 'feed', + 'feed_id' => $feed_id, + '_ANCHOR' => 'entries' + ) + ); + + if ($posts_actions_page->process()) { + return null; + } + + /* Get posts + -------------------------------------------------------- */ + $user_id = !empty($_GET['user_id']) ? $_GET['user_id'] : ''; + $cat_id = !empty($_GET['cat_id']) ? $_GET['cat_id'] : ''; + $status = isset($_GET['status']) ? $_GET['status'] : ''; + $selected = isset($_GET['selected']) ? $_GET['selected'] : ''; + $month = !empty($_GET['month']) ? $_GET['month'] : ''; + $lang = !empty($_GET['lang']) ? $_GET['lang'] : ''; + $sortby = !empty($_GET['sortby']) ? $_GET['sortby'] : 'post_dt'; + $order = !empty($_GET['order']) ? $_GET['order'] : 'desc'; + + $show_filters = false; + + $page = !empty($_GET['page']) ? (integer) $_GET['page'] : 1; + $nb_per_page = 30; + + if (!empty($_GET['nb']) && (integer) $_GET['nb'] > 0) { + if ($nb_per_page != $_GET['nb']) { + $show_filters = true; + } + $nb_per_page = (integer) $_GET['nb']; + } + + $params['limit'] = array((($page-1)*$nb_per_page), $nb_per_page); + $params['no_content'] = true; + + # - User filter + if ($user_id !== '' && in_array($user_id, $users_combo)) { + $params['user_id'] = $user_id; + $show_filters = true; + } + # - Categories filter + if ($cat_id !== '' && in_array($cat_id, $categories_combo)) { + $params['cat_id'] = $cat_id; + $show_filters = true; + } + # - Status filter + if ($status !== '' && in_array($status, $status_combo)) { + $params['post_status'] = $status; + $show_filters = true; + } + # - Selected filter + if ($selected !== '' && in_array($selected, $selected_combo)) { + $params['post_selected'] = $selected; + $show_filters = true; + } + # - Month filter + if ($month !== '' && in_array($month, $dt_m_combo)) { + $params['post_month'] = substr($month, 4, 2); + $params['post_year'] = substr($month, 0, 4); + $show_filters = true; + } + # - Lang filter + if ($lang !== '' && in_array($lang, $lang_combo)) { + $params['post_lang'] = $lang; + $show_filters = true; + } + # - Sortby and order filter + if ($sortby !== '' && in_array($sortby, $sortby_combo)) { + if ($order !== '' && in_array($order, $order_combo)){ + $params['order'] = $sortby.' '.$order; + } + if ($sortby != 'post_dt' || $order != 'desc') { + $show_filters = true; + } + } + + # Get posts + try { + $params['feed_id'] = $feed_id; + $posts = $zcfs->getPostsByFeed($params); + $counter = $zcfs->getPostsByFeed($params,true); + $post_list = new zcfsEntriesList( + $core, + $posts, + $counter->f(0) + ); + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } + } + + # Display + echo + ''.__('Feeds server').''. + ($feed_id && !$core->error->flag() ? + dcPage::jsLoad( + 'index.php?pf=periodical/js/postsfilter.js' + ). + '\n" + : ''). + dcPage::jsPageTabs(). + $next_headlink."\n".$prev_headlink. + + # --BEHAVIOR-- packmanAdminHeader + $core->callBehavior('zcfsAdminHeader', $core). + + ''. + + dcPage::breadcrumb( + array( + html::escapeHTML($core->blog->name) => '', + __('Feeds server') => '', + __('Feeds') => $p_url, + ($feed_id ? __('Edit feed') : __('New feed')) => '' + ) + ). + dcPage::notices(); + + # Feed + if ($can_view_page) { + + # nav link + if ($feed_id && ($next_link || $prev_link)) { + echo '

    '; + if ($prev_link) { + echo $prev_link; + } + if ($next_link && $prev_link) { + echo ' - '; + } + if ($next_link) { + echo $next_link; + } + echo '

    '; + } + + echo ' +
    +
    + +
    '. + + '
    '. + '

    '.__('Feed information').'

    '. + + '

    '. + form::field('feed_name', 60, 255, $feed_name, 'maximal'). + '

    '. + + '

    '. + form::field('feed_owner', 60, 255, $feed_owner, 'maximal'). + '

    '. + + // move this away + '

    '. + form::field('feed_tweeter', 60, 64, $feed_tweeter, 'maximal'). + '

    '. + + '

    '. + form::field('feed_url', 60, 255, $feed_url, 'maximal'). + '

    '. + + '

    '. + form::field('feed_feed', 60, 255, $feed_feed, 'maximal'). + '

    '. + + '

    '. + form::field('feed_desc', 60, 255, $feed_desc, 'maximal'). + '

    '. + + '

    '. + form::field('feed_tags', 60, 255, $feed_tags, 'maximal'). + '

    '. + + # --BEHAVIOR-- zoneclearFeedServerFeedForm + $core->callBehavior('zoneclearFeedServerFeedForm', $core, $feed_id). + + '
    '. + + '
    '. + '

    '.__('Local settings').'

    '. + + '

    '. + form::combo('feed_cat_id', $combo_categories, $feed_cat_id, 'maximal'). + '

    '. + + '

    '. + form::combo('feed_status', $combo_status, $feed_status, 'maximal'). + '

    '. + + '

    '. + form::combo('feed_upd_int', $combo_upd_int, $feed_upd_int, 'maximal'). + '

    '. + + '

    '. + form::combo('feed_lang', $combo_langs, $feed_lang, 'maximal'). + '

    '. + + '

    '. + + '
    '. + + '
    '. + + '

    '. + form::hidden(array('action'), 'savefeed'). + form::hidden(array('feed_id'), $feed_id). + form::hidden(array('p'), 'zoneclearFeedServer'). + form::hidden(array('part'), 'feed'). + $core->formNonce(). + '

    +
    +
    '; + } + + # Entries + if ($feed_id && $can_view_page && !$core->error->flag()) { + echo + '
    '. + + '
    '. + + '

    '. + __('Cancel filters and display options'). + '

    '. + + '
    '. + '
    '. + '

    '.__('Filters').'

    '. + '

    '. + form::combo('user_id',$users_combo,$user_id).'

    '. + '

    '. + form::combo('cat_id',$categories_combo,$cat_id).'

    '. + '

    ' . + form::combo('status',$status_combo,$status).'

    '. + '
    '. + + '
    '. + '

    '. + form::combo('selected',$selected_combo,$selected).'

    '. + '

    '. + form::combo('month',$dt_m_combo,$month).'

    '. + '

    '. + form::combo('lang',$lang_combo,$lang).'

    '. + '
    '. + + '
    '. + '

    '.__('Display options').'

    '. + '

    '. + form::combo('sortby',$sortby_combo,$sortby).'

    '. + '

    '. + form::combo('order',$order_combo,$order).'

    '. + '

    '.__('Show').'

    '. + '
    '. + '
    '. + + '

    '. + form::hidden(array('p'), 'zoneclearFeedServer'). + form::hidden(array('part'), 'feed'). + form::hidden(array('feed_id') ,$feed_id). + '
    '. //Opera sucks + '

    '. + '
    '. + + # Show posts + $post_list->display($page, $nb_per_page, + + $p_url. + '&part=feed'. + '&tab=entries'. + '&feed_id='.$feed_id. + '&user_id='.$user_id. + '&cat_id='.$cat_id. + '&status='.$status. + '&selected='.$selected. + '&month='.$month. + '&lang='.$lang. + '&sortby='.$sortby. + '&order='.$order. + '&nb='.$nb_per_page. + '&page=%s', + + '
    '. + '%s'. + + '
    '. + '

    '. + + '

    '.__('Selected entries action:').' '. + form::combo('action', $posts_actions_page->getCombo()). + '

    '. + form::hidden(array('part'), 'feed'). + form::hidden(array('feed_id'), $feed_id). + form::hidden(array('user_id'), $user_id). + form::hidden(array('cat_id'), $cat_id). + form::hidden(array('status'), $status). + form::hidden(array('selected'), $selected). + form::hidden(array('month'), $month). + form::hidden(array('lang'), $lang). + form::hidden(array('sortby'), $sortby). + form::hidden(array('order'), $order). + form::hidden(array('page'), $page). + form::hidden(array('nb'), $nb_per_page). + $core->formNonce(). + '
    '. + '
    ' + ); + + echo + '
    '; + } +} + +############################################################ +# +# All feeds +# +############################################################ + +else { + + # Actions page + $feeds_actions_page = new zcfsFeedsActionsPage( + $core, + 'plugin.php', + array('p' => 'zoneclearFeedServer', 'part' => 'feeds') + ); + + if ($feeds_actions_page->process()) { + + return null; + } + + # Combos + $combo_sortby = array( + __('Date') => 'feed_upddt', + __('Name') => 'lowername', + __('Frequency') => 'feed_upd_int', + __('Date of update') => 'feed_upd_last', + __('Status') => 'feed_status' + ); + + $combo_order = array( + __('Descending') => 'desc', + __('Ascending') => 'asc' + ); + + # Prepared lists + $show_filters = false; + $sortby = !empty($_GET['sortby']) ? $_GET['sortby'] : 'feed_upddt'; + $order = !empty($_GET['order']) ? $_GET['order'] : 'desc'; + $page = !empty($_GET['page']) ? (integer) $_GET['page'] : 1; + $nb_per_page = 30; + if (!empty($_GET['nb']) && (integer) $_GET['nb'] > 0) { + if ($nb_per_page != $_GET['nb']) $show_filters = true; + $nb_per_page = (integer) $_GET['nb']; + } + + $params = array(); + $params['limit'] = array((($page-1)*$nb_per_page), $nb_per_page); + + if ($sortby != '' && in_array($sortby, $combo_sortby)) { + if ($order != '' && in_array($order, $combo_order)) { + $params['order'] = $sortby.' '.$order; + } + if ($sortby != 'feed_upddt' || $order != 'desc') { + $show_filters = true; + } + } + + $pager_base_url = $p_url. + '&part=feeds'. + '&sortby='.$sortby. + '&order='.$order. + '&nb='.$nb_per_page. + '&page=%s'; + + try { + $feeds = $zcfs->getFeeds($params); + $feeds_counter = $zcfs->getFeeds($params, true)->f(0); + $feeds_list = new zcfsFeedsList( + $core, + $feeds, + $feeds_counter, + $pager_base_url + ); + } + catch (Exception $e) { + $core->error->add($e->getMessage()); + } + + # Display + echo + ''.__('Feeds server').''. + dcPage::jsLoad( + 'index.php?pf=zoneclearFeedServer/js/feedsfilter.js' + ). + '\n". + dcPage::jsPageTabs(). + + # --BEHAVIOR-- packmanAdminHeader + $core->callBehavior('zcfsAdminHeader', $core). + + ''. + + dcPage::breadcrumb( + array( + html::escapeHTML($core->blog->name) => '', + __('Feeds server') => '', + __('Feeds') => '' + ) + ). + dcPage::notices(). + + '

    '. + ''. + __('New feed').'

    '. + + '
    '. + '

    '.__('Show filters and display options').'

    '. + + '
    '. + '
    '. + '

    '. + form::combo('sortby',$combo_sortby, $sortby).'

    '. + '
    '. + '
    '. + '

    '. + form::combo('order',$combo_order, $order).'

    '. + '
    '. + '
    '. + '

    '.__('Show').'

    '. + '
    '. + '
    '. + + '

    '. + form::hidden(array('p'), 'zoneclearFeedServer'). + form::hidden(array('part'), 'feeds'). + '

    '. //Opera sucks + '
    '. + + $feeds_list->feedsDisplay($page, $nb_per_page, $pager_base_url, + '
    '. + '%s'. + '
    '. + '

    '. + '

    '.__('Selected feeds action:').' '. + form::combo(array('action'), $feeds_actions_page->getCombo()). + ''. + form::hidden(array('sortby'), $sortby). + form::hidden(array('order'), $order). + form::hidden(array('page'), $page). + form::hidden(array('nb'), $nb_per_page). + form::hidden(array('p'), 'zoneclearFeedServer'). + form::hidden(array('part'), 'feeds'). + $core->formNonce(). + '

    '. + '
    '. + '
    ' + ); +} + +echo +'

    +'.__('Configuration').' - +zoneclearFeedServer - '.$core->plugins->moduleInfo('zoneclearFeedServer', 'version').'  +'.__('zoneclearFeedServer').' +

    +'; \ No newline at end of file diff --git a/js/feedsfilter.js b/js/feedsfilter.js new file mode 100644 index 0000000..188882b --- /dev/null +++ b/js/feedsfilter.js @@ -0,0 +1,31 @@ +$(function(){ + $('.checkboxes-helpers').each(function(){dotclear.checkboxesHelpers(this);}); + + $filtersform = $('#filters-form'); + $filtersform.before('

    '+dotclear.msg.filter_posts_list+'

    ') + + if( dotclear.msg.show_filters == 'false' ) { + $filtersform.hide(); + } else { + $('#filter-control') + .addClass('open') + .text(dotclear.msg.cancel_the_filter); + } + + $('#filter-control').click(function() { + if( $(this).hasClass('open') ) { + if( dotclear.msg.show_filters == 'true' ) { + return true; + } else { + $filtersform.hide(); + $(this).removeClass('open') + .text(dotclear.msg.filter_posts_list); + } + } else { + $filtersform.show(); + $(this).addClass('open') + .text(dotclear.msg.cancel_the_filter); + } + return false; + }); +}); \ No newline at end of file diff --git a/js/post.js b/js/post.js new file mode 100644 index 0000000..4b3e492 --- /dev/null +++ b/js/post.js @@ -0,0 +1,7 @@ +$(function(){ + /* toogle admin form sidebar */ + $('#zcfs h5').toggleWithLegend( + $('#zcfs').children().not('h5'), + {cookie:'dcx_zcfs_admin_form_sidebar',legend_click:true} + ); +}); \ No newline at end of file diff --git a/js/postsfilter.js b/js/postsfilter.js new file mode 100644 index 0000000..2a12570 --- /dev/null +++ b/js/postsfilter.js @@ -0,0 +1,31 @@ +$(function(){ + $('.checkboxes-helpers').each(function(){dotclear.checkboxesHelpers(this);}); + + $filtersform = $('#filters-form'); + $filtersform.before('

    '+dotclear.msg.filter_posts_list+'

    ') + + if( dotclear.msg.show_filters == 'false' ) { + $filtersform.hide(); + } else { + $('#filter-control') + .addClass('open') + .text(dotclear.msg.cancel_the_filter); + } + + $('#filter-control').click(function() { + if( $(this).hasClass('open') ) { + if( dotclear.msg.show_filters == 'true' ) { + return true; + } else { + $filtersform.hide(); + $(this).removeClass('open') + .text(dotclear.msg.filter_posts_list); + } + } else { + $filtersform.show(); + $(this).addClass('open') + .text(dotclear.msg.cancel_the_filter); + } + return false; + }); +}); \ No newline at end of file diff --git a/locales/en/help/zoneclearFeedServer.html b/locales/en/help/zoneclearFeedServer.html new file mode 100644 index 0000000..2ae9478 --- /dev/null +++ b/locales/en/help/zoneclearFeedServer.html @@ -0,0 +1,15 @@ + + + + Configure ZoneclearFeedServer + + +

    Informations

    +
      +
    • A writable cache folder is required to use this plugin.
    • +
    • If you set a large number of feeds to update at one time, this may cause a timeout error. We recommand to keep it to one.
    • +
    • If you use cron script, you can disable public update.
    • +
    • In order to do update through Ajax, your theme must have behavior publicHeadContent.
    • +
    + + \ No newline at end of file diff --git a/locales/en/resources.php b/locales/en/resources.php new file mode 100644 index 0000000..c453820 --- /dev/null +++ b/locales/en/resources.php @@ -0,0 +1,17 @@ + + + + Configuration de ZoneclearFeedServer + + +

    Informations

    +
      +
    • Un dossier de cache accessible en écriture est nécessaire pour utiliser ce plugin.
    • +
    • Si vous paramétrez un grand nombre de flux à mettre à jour, ceci peut causer une erreur de timeout. Il est recommandé de laisser cette valeur à 1.
    • +
    • Si vous utilisez un script cron, vous pouvez désactiver la mise à jour publique.
    • +
    • Pour utiliser la mise à jour depuis Ajax, votre thème doit avoir le behavior publicheadContent.
    • +
    + + \ No newline at end of file diff --git a/locales/fr/main.po b/locales/fr/main.po new file mode 100644 index 0000000..04a8bbe --- /dev/null +++ b/locales/fr/main.po @@ -0,0 +1,548 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: zoneclearFeedServer 2013.07.12\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2013-11-19T08:03:53+00:00\n" +"Last-Translator: Jean-Christian Denis\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Mix your blog with a feeds planet" +msgstr "Mixer votre blog avec un planet" + +#: _admin.php:35 +#: _admin.php:95 +#: inc/class.zcfs.feedsactions.php:34 +#: inc/class.zcfs.feedsactions.php:304 +#: inc/class.zcfs.feedsactions.php:357 +#: index.php:435 +#: index.php:468 +#: index.php:763 +#: index.php:793 +msgid "Feeds server" +msgstr "Serveur de flux" + +#: _admin.php:143 +msgid "%s feed disabled" +msgid_plural "%s feeds disabled" +msgstr[0] "%s flux désactivé" +msgstr[1] "%s flux désactivés" + +#: _admin.php:224 +msgid "Edit this feed" +msgstr "Modifier ce flux" + +#: _admin.php:230 +msgid "Feed source" +msgstr "Source du flux" + +#: _admin.php:232 +msgid "feed URL" +msgstr "URL du fil" + +#: _admin.php:233 +msgid "site URL" +msgstr "URL du site" + +#: _config.php:98 +msgid "Disable" +msgstr "Désactiver" + +#: _config.php:99 +msgid "Before display" +msgstr "Avant l'affichage" + +#: _config.php:100 +msgid "After display" +msgstr "Après l'affichage" + +#: _config.php:101 +msgid "Through Ajax" +msgstr "À travers Ajax" + +#: _config.php:108 +msgid "Keep source case" +msgstr "Garder la casse de la source" + +#: _config.php:109 +msgid "First upper case" +msgstr "Premier caractère en majuscule" + +#: _config.php:110 +msgid "All lower case" +msgstr "Tout en minuscule" + +#: _config.php:111 +msgid "All upper case" +msgstr "Tout en majuscule" + +#: _config.php:121 +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é !" + +#: _config.php:132 +msgid "Enable plugin" +msgstr "Activer le plugin" + +#: _config.php:136 +msgid "View the public list of feeds" +msgstr "Voir la page publique de la liste des flux" + +#: _config.php:141 +msgid "Rules" +msgstr "Règles" + +#: _config.php:146 +msgid "Status of new posts:" +msgstr "Status des nouveaux billets :" + +#: _config.php:150 +msgid "Owner of entries created by zoneclearFeedServer:" +msgstr "Propriétaire des billets créés par zoneclearFeedServer :" + +#: _config.php:154 +msgid "How to transform imported tags:" +msgstr "Comment tranformer la casse des mots-clés importés :" + +#: _config.php:160 +msgid "Update feeds on public side:" +msgstr "Mettre à jour les flux depuis la partie publique :" + +#: _config.php:164 +msgid "Number of feeds to update at one time:" +msgstr "Nombre de flux à mettre à jour à la fois :" + +#: _config.php:169 +msgid "Keep active empty feeds" +msgstr "Garder actif les flux vides" + +#: _config.php:173 +msgid "Enable public page" +msgstr "Activer la page publique" + +#: _config.php:177 +msgid "Redirect to original post on:" +msgstr "Rediriger vers le billet original sur :" + +#: _config.php:194 +msgid "Show full content on:" +msgstr "Afficher le contenu complet sur :" + +#: _public.php:234 +msgid "Original post on %s" +msgstr "Billet original sur %s" + +#: _public.php:245 +msgid "Read more details about this feed" +msgstr "Lire plus de détails à propos de ce flux" + +#: _widgets.php:35 +msgid "Feeds server: sources" +msgstr "Serveur de flux : les sources" + +#: _widgets.php:38 +msgid "List sources of feeds" +msgstr "Liste des sources du flux" + +#: _widgets.php:43 +msgid "Feeds sources" +msgstr "Sources des flux" + +#: _widgets.php:54 +msgid "Create date" +msgstr "Date de création" + +#: _widgets.php:69 +msgid "Limit:" +msgstr "Limite :" + +#: _widgets.php:75 +msgid "Add link to feeds page" +msgstr "Ajouter un lien vers la page des flux" + +#: _widgets.php:107 +msgid "Feeds server: numbers" +msgstr "Serveur de flux : les chiffres" + +#: _widgets.php:110 +msgid "Show some numbers about feeds" +msgstr "Affciher quelques chiffres à propose du flux" + +#: _widgets.php:115 +msgid "Feeds numbers" +msgstr "Le flux en chiffres" + +#: _widgets.php:122 +msgid "Show feeds count" +msgstr "Afficher le nombre de flux" + +#: _widgets.php:128 +msgid "Title for feeds count:" +msgstr "Titre pour le nombre de flux :" + +#: _widgets.php:129 +msgid "Feeds:" +msgstr "Flux :" + +#: _widgets.php:136 +msgid "Show entries count" +msgstr "Afficher le nombre de billets" + +#: _widgets.php:142 +msgid "Title for entries count:" +msgstr "Titre pour le nombre de billets :" + +#: _widgets.php:143 +msgid "Entries:" +msgstr "Billets :" + +#: _widgets.php:208 +msgid "All sources" +msgstr "Toutes les sources" + +#: _widgets.php:241 +msgid "no sources" +msgstr "aucune source" + +#: _widgets.php:244 +msgid "one source" +msgstr "une source" + +#: _widgets.php:247 +msgid "%d sources" +msgstr "%d sources" + +#: _widgets.php:270 +msgid "no entries" +msgstr "aucun billet" + +#: _widgets.php:273 +msgid "one entry" +msgstr "un billet" + +#: _widgets.php:308 +msgid "%d entries" +msgstr "%d billets" + +#: default-templates/zcfeeds.html:50 +msgid "List of feeds" +msgstr "Liste des sources" + +#: inc/class.zcfs.feedsactions.php:21 +#: index.php:469 +#: index.php:794 +msgid "Feeds" +msgstr "Flux de syndication" + +#: inc/class.zcfs.feedsactions.php:40 +msgid "Back to feeds list" +msgstr "Retour à la liste des flux" + +#: inc/class.zcfs.feedsactions.php:55 +msgid "Feeds actions" +msgstr "Actions sur les flux" + +#: inc/class.zcfs.feedsactions.php:95 +msgid "Change update interval" +msgstr "Changer l'interval de mise à jour" + +#: inc/class.zcfs.feedsactions.php:99 +msgid "Disable feed update" +msgstr "Désactiver la mise à jour du flux" + +#: inc/class.zcfs.feedsactions.php:103 +msgid "Enable feed update" +msgstr "Activer la mise à jour du flux" + +#: inc/class.zcfs.feedsactions.php:107 +msgid "Reset last update" +msgstr "Remettre à zéro le chronomètre de mise à jour" + +#: inc/class.zcfs.feedsactions.php:111 +msgid "Update (check) feed" +msgstr "Mettre à jour (vérifier) le flux" + +#: inc/class.zcfs.feedsactions.php:115 +msgid "Delete related posts" +msgstr "Effacer les billets liés" + +#: inc/class.zcfs.feedsactions.php:119 +msgid "Delete feed (without related posts)" +msgstr "Effacer le flux (sans effacer les billets liés)" + +#: inc/class.zcfs.feedsactions.php:130 +#: inc/class.zcfs.feedsactions.php:169 +#: inc/class.zcfs.feedsactions.php:200 +#: inc/class.zcfs.feedsactions.php:223 +#: inc/class.zcfs.feedsactions.php:246 +#: inc/class.zcfs.feedsactions.php:273 +#: inc/class.zcfs.feedsactions.php:330 +msgid "No feeds selected" +msgstr "Aucun flux selectionné" + +#: inc/class.zcfs.feedsactions.php:140 +msgid "%d feed has been successfully enabled." +msgid_plural "%d feeds have been successfully enabled." +msgstr[0] "%s flux activé avec succès." +msgstr[1] "%s flux activés avec succès." + +#: inc/class.zcfs.feedsactions.php:146 +msgid "%d feed has been successfully disabled." +msgid_plural "%d feeds have been successfully disabled." +msgstr[0] "%s flux désactivé avec succès." +msgstr[1] "%s flux désactivés avec succès." + +#: inc/class.zcfs.feedsactions.php:190 +msgid "Entries have been successfully deleted." +msgstr "Les billets ont été effacé avec succès." + +#: inc/class.zcfs.feedsactions.php:209 +msgid "%d feed has been successfully deleted." +msgid_plural "%d feeds have been successfully deleted." +msgstr[0] "%s flux effacé avec succès." +msgstr[1] "%s flux effacés avec succès." + +#: inc/class.zcfs.feedsactions.php:232 +msgid "%d feed has been successfully updated." +msgid_plural "%d feeds have been successfully updated." +msgstr[0] "%s flux mis à jour avec succès." +msgstr[1] "%s flux mis à jour avec succès." + +#: inc/class.zcfs.feedsactions.php:209 +msgid "Last update of %s feed successfully reseted." +msgid_plural "Last update of %s feeds successfully reseted." +msgstr[0] "Date de dernière mise à jour de %s flux remise à zéro avec succès." +msgstr[1] "Dates de dernières mises à jour de %s flux remises à zéro avec succès." + +#: inc/class.zcfs.feedsactions.php:286 +msgid "Category of %s feed successfully changed." +msgid_plural "Category of %s feeds successfully changed." +msgstr[0] "Catégorie de %s flux mise à jour avec succès." +msgstr[1] "Catégorie de %s flux mise à jour avec succès." + +#: inc/class.zcfs.feedsactions.php:343 +msgid "Update frequency of %s feed successfully changed." +msgid_plural "Update frequency of %s feeds successfully changed." +msgstr[0] "Fréquence de mise à jour de %s flux modifiée avec succès." +msgstr[1] "Fréquence de mise à jour de %s flux modifiée avec succès." + +#: inc/class.zcfs.feedsactions.php:359 +msgid "Change update frequency for this selection" +msgstr "Changer la fréquence de mise à jour pour la selection" + +#: inc/class.zcfs.feedsactions.php:365 +msgid "Frequency:" +msgstr "Fréquence :" + +#: inc/class.zoneclear.feed.server.php:822 +msgid "Disabled" +msgstr "Désactivé" + +#: inc/class.zoneclear.feed.server.php:823 +msgid "Enabled" +msgstr "Activé" + +#: inc/class.zoneclear.feed.server.php:835 +msgid "Every hour" +msgstr "Toutes les heures" + +#: inc/class.zoneclear.feed.server.php:836 +msgid "Every two hours" +msgstr "Toutes les deux heures" + +#: inc/class.zoneclear.feed.server.php:837 +msgid "Two times per day" +msgstr "Deux fois par jour" + +#: inc/class.zoneclear.feed.server.php:838 +msgid "Every day" +msgstr "Chaque jour" + +#: inc/class.zoneclear.feed.server.php:839 +msgid "Every two days" +msgstr "Tous les deux jours" + +#: inc/class.zoneclear.feed.server.php:911 +msgid "Home page" +msgstr "Page d'accueil" + +#: inc/class.zoneclear.feed.server.php:912 +msgid "Entries pages" +msgstr "Pages des billets" + +#: inc/class.zoneclear.feed.server.php:913 +msgid "Tags pages" +msgstr "Pages des mots-clés" + +#: inc/class.zoneclear.feed.server.php:914 +msgid "Archives pages" +msgstr "Pages des archives" + +#: inc/class.zoneclear.feed.server.php:915 +msgid "Category pages" +msgstr "Pages de catégories" + +#: inc/lib.zcfs.list.php:31 +msgid "There is no feed" +msgstr "Il n'y a pas de flux" + +#: inc/lib.zcfs.list.php:44 +#: index.php:494 +msgid "Feed" +msgstr "Flux" + +#: inc/lib.zcfs.list.php:74 +msgid "no categories" +msgstr "aucune catégorie" + +#: inc/lib.zcfs.list.php:101 +msgid "never" +msgstr "jamais" + +#: inc/lib.zcfs.list.php:107 +msgid "View entries" +msgstr "Voir les billets" + +#: inc/lib.zcfs.socialmewriter.php:32 +msgid "New Zoneclear post" +msgstr "Nouveu billet Zoneclear" + +#: inc/lib.zcfs.socialmewriter.php:33 +msgid "When a feed has new entry" +msgstr "Lorsqu'un flux a un nouveau billet" + +#: inc/lib.zcfsr.activityreport.php:23 +msgid "Plugin zoneclearFeedServer" +msgstr "Extension zoneclearFeedServer" + +#: inc/lib.zcfsr.activityreport.php:30 +msgid "feed creation" +msgstr "création d'un flux" + +#: inc/lib.zcfsr.activityreport.php:31 +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\"" + +#: inc/lib.zcfsr.activityreport.php:39 +msgid "updating feed info" +msgstr "mise à jour des informations du flux (administration)" + +#: inc/lib.zcfsr.activityreport.php:40 +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\"" + +#: inc/lib.zcfsr.activityreport.php:48 +msgid "updating feed records" +msgstr "mise à jour des enregistrements du flux (automatique)" + +#: inc/lib.zcfsr.activityreport.php:49 +msgid "Records of the feed named \"%s\" have been updated automatically" +msgstr "Les enregistrements du flux nommé \"%s\" ont été automatiquement mis à jour" + +#: inc/lib.zcfsr.activityreport.php:57 +msgid "feed deletion" +msgstr "suppression d'un flux" + +#: inc/lib.zcfsr.activityreport.php:58 +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\"" + +#: inc/lib.zcfsr.activityreport.php:66 +msgid "feed status" +msgstr "status d'un flux" + +#: inc/lib.zcfsr.activityreport.php:67 +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\"" + +#: index.php:84 +msgid "This feed does not exist." +msgstr "Ce flux n'existe pas." + +#: index.php:115 +msgid "next feed" +msgstr "flux suivant" + +#: index.php:122 +msgid "previous feed" +msgstr "flux précédent" + +#: index.php:151 +msgid "Record with same feed URL already exists." +msgstr "Un enregistrement avec la même URL de flux existe déjà." + +#: index.php:154 +msgid "You must provide a name." +msgstr "Vous devez indiquer un nom." + +#: index.php:157 +msgid "You must provide an owner." +msgstr "Vous devez indiquer un propriétaire." + +#: index.php:160 +msgid "You must provide valid site URL." +msgstr "Vous devez donner une URL de site valide." + +#: index.php:163 +msgid "You must provide valid feed URL." +msgstr "Vous devez donner une URL de flux valide." + +#: index.php:167 +msgid "You must provide valid category." +msgstr "Vous devez donner une catégorie valide." + +#: index.php:213 +msgid "Feed successfully updated." +msgstr "Flux mis à jour avec succès." + +#: index.php:241 +msgid "Feed successfully created." +msgstr "Flux créé avec succcès." + +#: index.php:470 +msgid "Edit feed" +msgstr "Edition de flux" + +#: index.php:470 +#: index.php:801 +msgid "New feed" +msgstr "Nouveau flux" + +#: index.php:500 +msgid "Feed information" +msgstr "Information sur le flux" + +#: index.php:510 +msgid "Owner:" +msgstr "Propriétaire :" + +#: index.php:516 +msgid "Tweeter or Identica ident:" +msgstr "Identifiant Twiiter ou Identi.ca :" + +#: index.php:522 +msgid "Site URL:" +msgstr "URL du site :" + +#: index.php:546 +msgid "Local settings" +msgstr "Paramètres locaux" + +#: index.php:556 +msgid "Update:" +msgstr "Mise à jour :" + +#: index.php:566 +msgid "Import tags from feed" +msgstr "Importer les tags depuis le flux" + +#: index.php:708 +msgid "Date of update" +msgstr "Date de mise à jour" + +#: index.php:833 +msgid "Selected feeds action:" +msgstr "Action sur les flux sélectionnés :" + diff --git a/locales/fr/resources.php b/locales/fr/resources.php new file mode 100644 index 0000000..c453820 --- /dev/null +++ b/locales/fr/resources.php @@ -0,0 +1,17 @@ +