diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d2852d9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +2.1 - 2022.12.31 +* update to dotclear 2.24 +* update to jquery plugin 2.1.0 (2016) +* fix phpstan and php-cs-fixer errors +* fix js call + +1.6 - 2022.12.28 - Pierre Van Glabeke +* màj partielle dc2.24 + +1.5 - 2016.07.29 - Pierre Van Glabeke +* mise à jour script jquery 1.6.3 -> 2.0.2 +* mise à jour pour compatibilité avec dc2.9 +* dc2.9 requis diff --git a/gpl-2.0.txt b/LICENSE similarity index 100% rename from gpl-2.0.txt rename to LICENSE diff --git a/README.md b/README.md index 4dfcbdf..884f709 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,52 @@ -# Countdown +# README -Le plugin propose un widget qui affiche un compte à rebours vers une date à venir ou un chronomètre vers une date passée. +[![Release](https://img.shields.io/github/v/release/JcDenis/countdown)](https://github.com/JcDenis/countdown/releases) +[![Date](https://img.shields.io/github/release-date/JcDenis/countdown)](https://github.com/JcDenis/countdown/releases) +[![Issues](https://img.shields.io/github/issues/JcDenis/countdown)](https://github.com/JcDenis/countdown/issues) +[![Dotclear](https://img.shields.io/badge/dotclear-v2.24-blue.svg)](https://fr.dotclear.org/download) +[![Dotaddict](https://img.shields.io/badge/dotaddict-official-green.svg)](https://plugins.dotaddict.org/dc2/details/countdown) +[![License](https://img.shields.io/github/license/JcDenis/countdown)](https://github.com/JcDenis/countdown/blob/master/LICENSE) -Documentation +## WHAT IS COUNTDOWN ? -L'affichage dynamique utilise le plugin jQuery Countdown (http://keith-wood.name/countdown.html) qui propose une syntaxe riche pour le formatage (http://keith-wood.name/countdownRef.html#format) et l'affichage (http://keith-wood.name/countdownRef.html#layout). \ No newline at end of file +_countdown_ is a plugin for the open-source +web publishing software called Dotclear. + +It adds widget showing a countdown since/from a predefined date. + +## REQUIREMENTS + + _countdown_ requires: + + * permissions to manage widgets + * Dotclear 2.24 + * jQuery libs + +## USAGE + +First install _countdown_, manualy from a zip package or from +Dotaddict repository. (See Dotclear's documentation to know how do this) + +Add and configure "Countdown" from widgets manager. + +## LINKS + + * License : [GNU GPL v2](https://www.gnu.org/licenses/old-licenses/lgpl-2.0.html) + * Source & contribution : [GitHub Page](https://github.com/JcDenis/countdown) + * Packages & details : [Dotaddict Page](https://plugins.dotaddict.org/dc2/details/countdown) + * Discuss & help : [Dotclear forum](https://forum.dotclear.org/viewforum.php?id=16) + +## CONTRIBUTORS + + * [Moe](http://gniark.net/) (author) + * Pierre Van Glabeke + * Jean-Christian Denis + + You are welcome to contribute to this code. + + ## JQUERY PLUGIN + +Dynamic display uses plugin jQuery Countdown; See: + * [Plugin](http://keith-wood.name/countdown.html) + * [Formats](http://keith-wood.name/countdownRef.html#format) + * [Display](http://keith-wood.name/countdownRef.html#layout) diff --git a/_admin.php b/_admin.php new file mode 100644 index 0000000..90da8cf --- /dev/null +++ b/_admin.php @@ -0,0 +1,17 @@ +. -# -# ***** END LICENSE BLOCK ***** - -if (!defined('DC_RC_PATH')) {return;} +registerModule( 'CountDown', 'Countdown and stopwatch', - 'Moe (http://gniark.net/), Pierre Van Glabeke', - '2.0.0', + 'Moe (http://gniark.net/) and contributors', + '2.1', [ 'requires' => [['core', '2.24']], 'permissions' => dcCore::app()->auth->makePermissions([ dcAuth::PERMISSION_ADMIN, ]), - 'type' => 'plugin', - 'support' => 'https://forum.dotclear.org/viewforum.php?id=16', - 'details' => 'http://plugins.dotaddict.org/dc2/details/countdown' + 'type' => 'plugin', + 'support' => 'https://forum.dotclear.org/viewforum.php?id=16', + 'details' => 'https://plugins.dotaddict.org/dc2/details/' . basename(__DIR__), + 'repository' => 'https://raw.githubusercontent.com/JcDenis/' . basename(__DIR__) . '/master/dcstore.xml', ] ); diff --git a/_prepend.php b/_prepend.php deleted file mode 100644 index fbbb162..0000000 --- a/_prepend.php +++ /dev/null @@ -1,24 +0,0 @@ -. -# -# ***** END LICENSE BLOCK ***** - -if (!defined('DC_RC_PATH')) {return;} - -require_once(dirname(__FILE__).'/_widget.php'); \ No newline at end of file diff --git a/_public.php b/_public.php new file mode 100644 index 0000000..295c855 --- /dev/null +++ b/_public.php @@ -0,0 +1,17 @@ +. -# -# ***** END LICENSE BLOCK ***** +addBehavior( + 'initWidgets', + ['CountDownBehaviors','initWidgets'] +); -dcCore::app()->addBehavior('initWidgets', - array('CountDownBehaviors','initWidgets')); - class CountDownBehaviors { - public static function initWidgets($w) - { - # set timezone - dcCore::app(); - $tz = dcCore::app()->blog->settings->system->blog_timezone; + public static function initWidgets($w) + { + $tz = dcCore::app()->blog->settings->get('system')->get('blog_timezone'); - $w->create('CountDown',__('Countdown'), - array('CountDownBehaviors','Show'), - null, - __('A countdown to a future date or stopwatch to a past date')); + $array_year = $array_month = $array_day = $array_hour = []; + $array_minute = $array_number_of_times = []; + for ($i = 1902;$i <= 2037;$i++) { + $array_year[$i] = $i; + } + for ($i = 1;$i <= 12;$i++) { + $i = str_repeat('0', (2 - strlen($i))) . $i; + $array_month[ucfirst(__(strftime('%B', mktime(0, 0, 0, (int) $i, 1, 1970)))) . ' (' . $i . ')'] = $i; + } + for ($i = 1;$i <= 31;$i++) { + $i = str_repeat('0', (2 - strlen($i))) . $i; + $array_day[$i] = $i; + } + for ($i = 0;$i <= 23;$i++) { + $i = str_repeat('0', (2 - strlen($i))) . $i; + $array_hour[$i] = $i; + } + for ($i = 0;$i <= 60;$i++) { + $i = str_repeat('0', (2 - strlen($i))) . $i; + $array_minute[$i] = $i; + } + for ($i = 1;$i <= 5;$i++) { + $array_number_of_times[$i] = $i; + } + $array_number_of_times['6 (' . __('all') . ')'] = 6; - $w->CountDown->setting('title',__('Title:'),__('CountDown'),'text'); + $w->create( + 'CountDown', + __('Countdown'), + ['CountDownBehaviors', 'Show'], + null, + __('A countdown to a future date or stopwatch to a past date') + ) + ->addTitle(__('CountDown')) + ->setting( + 'text_before', + __('Text displayed if the date is in the future:'), + __('In'), + 'text' + ) + ->setting( + 'text_after', + __('Text displayed if the date is in the past:'), + __('For'), + 'text' + ) - $w->CountDown->setting('text_before', - __('Text displayed if the date is in the future:'),__('In'),'text'); + ->setting('year', ucfirst(__('year')) . ':', dt::str('%Y', null, $tz), 'combo', $array_year) + ->setting('month', ucfirst(__('month')) . ':', dt::str('%m', null, $tz), 'combo', $array_month) + ->setting('day', ucfirst(__('day')) . ':', dt::str('%d', null, $tz), 'combo', $array_day) + ->setting('hour', ucfirst(__('hour')) . ':', dt::str('%H', null, $tz), 'combo', $array_hour) + ->setting('minute', ucfirst(__('minute')) . ':', dt::str('%M', null, $tz), 'combo', $array_minute) + ->setting('second', ucfirst(__('second')) . ':', dt::str('%S', null, $tz), 'combo', $array_minute) - $w->CountDown->setting('text_after', - __('Text displayed if the date is in the past:'),__('For'),'text'); + ->setting( + 'number_of_times', + __('Number of values to be displayed:'), + '6', + 'combo', + $array_number_of_times + ) + ->setting( + 'zeros', + __('Show zeros before hours, minutes and seconds'), + false, + 'check' + ) + ->setting( + 'dynamic', + __('Enable dynamic display'), + false, + 'check' + ) + ->setting( + 'dynamic_format', + sprintf( + __('Dynamic display format (see jQuery Countdown Reference):'), + 'http://keith-wood.name/countdownRef.html#format', + 'onclick="return window.confirm(\'' . + __('Are you sure you want to leave this page?') . '\')"' + ), + __('yowdHMS'), + 'text' + ) + ->setting( + 'dynamic_layout_before', + sprintf( + __('Dynamic display layout if the date is in the future (see jQuery Countdown Reference):'), + 'http://keith-wood.name/countdownRef.html#layout', + 'onclick="return window.confirm(\'' . + __('Are you sure you want to leave this page?') . '\')"' + ), + __('In {y<}{yn} {yl}, {y>} {o<}{on} {ol}, {o>} {w<}{wn} {wl}, {w>} {d<}{dn} {dl}, {d>} {hn} {hl}, {mn} {ml} and {sn} {sl}'), + 'textarea' + ) + ->setting( + 'dynamic_layout_after', + sprintf( + __('Dynamic display layout if the date is in the past (see jQuery Countdown Reference):'), + 'http://keith-wood.name/countdownRef.html#layout', + 'onclick="return window.confirm(\'' . + __('Are you sure you want to leave this page?') . '\')"' + ), + __('For {y<}{yn} {yl}, {y>} {o<}{on} {ol}, {o>} {w<}{wn} {wl}, {w>} {d<}{dn} {dl}, {d>} {hn} {hl}, {mn} {ml} and {sn} {sl}'), + 'textarea' + ) - # create arrays for year, month, day, hour, minute and second - $array_year = $array_month = $array_day = $array_hour = array(); - $array_minute = $array_number_of_times = array(); - for ($i = 1902;$i <= 2037;$i++) - { - $array_year[$i] = $i; - } - for ($i = 1;$i <= 12;$i++) - { - $i = str_repeat('0',(2-strlen($i))).$i; - $array_month[ucfirst(__(strftime('%B', mktime(0, 0, 0, $i, 1, 1970)))).' ('.$i.')'] = $i; - } - for ($i = 1;$i <= 31;$i++) - { - $i = str_repeat('0',(2-strlen($i))).$i; - $array_day[$i] = $i; - } - for ($i = 0;$i <= 23;$i++) - { - $i = str_repeat('0',(2-strlen($i))).$i; - $array_hour[$i] = $i; - } - for ($i = 0;$i <= 60;$i++) - { - $i = str_repeat('0',(2-strlen($i))).$i; - $array_minute[$i] = $i; - } - for ($i = 1;$i <= 5;$i++) - { - $array_number_of_times[$i] = $i; - } - $array_number_of_times['6 ('.__('all').')'] = 6; - # /create arrays + ->addHomeOnly() + ->addContentOnly() + ->addClass() + ->addOffline(); + } - $w->CountDown->setting('year',ucfirst(__('year')).':', - dt::str('%Y',null,$tz),'combo',$array_year); - $w->CountDown->setting('month',ucfirst(__('month')).':', - dt::str('%m',null,$tz),'combo',$array_month); - $w->CountDown->setting('day',ucfirst(__('day')).':', - dt::str('%d',null,$tz),'combo',$array_day); - $w->CountDown->setting('hour',ucfirst(__('hour')).':', - dt::str('%H',null,$tz),'combo',$array_hour); - $w->CountDown->setting('minute',ucfirst(__('minute')).':', - dt::str('%M',null,$tz),'combo',$array_minute); - $w->CountDown->setting('second',ucfirst(__('second')).':', - dt::str('%S',null,$tz),'combo',$array_minute); + # escape quotes but not XHTML tags + # inspired by html::escapeJS() + public static function escapeQuotes($str) + { + $str = str_replace("'", "\'", $str); + $str = str_replace('"', '\"', $str); - $w->CountDown->setting('number_of_times', - __('Number of values to be displayed:'),'6','combo', - $array_number_of_times); + return $str; + } - $w->CountDown->setting('zeros', - __('Show zeros before hours, minutes and seconds'),false,'check'); - - $w->CountDown->setting('dynamic', - __('Enable dynamic display'),false,'check'); - - $w->CountDown->setting('dynamic_format', - sprintf(__('Dynamic display format (see jQuery Countdown Reference):'), - 'http://keith-wood.name/countdownRef.html#format', - 'onclick="return window.confirm(\''. - __('Are you sure you want to leave this page?').'\')"'), - __('yowdHMS'),'text'); - - $w->CountDown->setting('dynamic_layout_before', - sprintf(__('Dynamic display layout if the date is in the future (see jQuery Countdown Reference):'), - 'http://keith-wood.name/countdownRef.html#layout', - 'onclick="return window.confirm(\''. - __('Are you sure you want to leave this page?').'\')"'), - __('In {y<}{yn} {yl}, {y>} {o<}{on} {ol}, {o>} {w<}{wn} {wl}, {w>} {d<}{dn} {dl}, {d>} {hn} {hl}, {mn} {ml} and {sn} {sl}'), - 'textarea'); - - $w->CountDown->setting('dynamic_layout_after', - sprintf(__('Dynamic display layout if the date is in the past (see jQuery Countdown Reference):'), - 'http://keith-wood.name/countdownRef.html#layout', - 'onclick="return window.confirm(\''. - __('Are you sure you want to leave this page?').'\')"'), - __('For {y<}{yn} {yl}, {y>} {o<}{on} {ol}, {o>} {w<}{wn} {wl}, {w>} {d<}{dn} {dl}, {d>} {hn} {hl}, {mn} {ml} and {sn} {sl}'), - 'textarea'); - - $w->CountDown->setting('homeonly',__('Display on:'),0,'combo', - array( - __('All pages') => 0, - __('Home page only') => 1, - __('Except on home page') => 2 - ) - ); - $w->CountDown->setting('content_only',__('Content only'),0,'check'); - $w->CountDown->setting('class',__('CSS class:'),''); - $w->CountDown->setting('offline',__('Offline'),0,'check'); - } - - # escape quotes but not XHTML tags - # inspired by html::escapeJS() - public static function escapeQuotes($str) - { - $str = str_replace("'","\'",$str); - $str = str_replace('"','\"',$str); - return $str; - } - - public static function Show($w) - { - # set timezone - dcCore::app(); + public static function Show($w) + { + if ($w->offline) { + return null; + } - if ($w->offline) - return; + if (!$w->checkHomeOnly(dcCore::app()->url->type)) { + return null; + } - if (($w->homeonly == 1 && dcCore::app()->url->type != 'default') || - ($w->homeonly == 2 && dcCore::app()->url->type == 'default')) { - return; - } + # get local time + $local_time = dt::addTimeZone(dcCore::app()->blog->settings->get('system')->get('blog_timezone')); - # get local time - $local_time = dt::addTimeZone(dcCore::app()->blog->settings->system->blog_timezone); + $ts = mktime($w->hour, $w->minute, $w->second, $w->month, $w->day, $w->year); + # get difference + (int) $diff = ($local_time - $ts); + $after = ($diff > 0) ? true : false; + $diff = abs($diff); - $ts = mktime($w->hour,$w->minute,$w->second,$w->month,$w->day, - $w->year); - # get difference - (int)$diff = ($local_time - $ts); - $after = ($diff > 0) ? true : false; - $diff = abs($diff); - - $times = array(); - - $intervals = array - ( - (3600*24*365.24) => array('one'=>__('year'),'more'=>__('years'), - 'zeros'=>false), - (3600*24*30.4) => array('one'=>__('month'),'more'=>__('months'), - 'zeros'=>false), - (3600*24) => array('one'=>__('day'),'more'=>__('days'), - 'zeros'=>false), - (3600) => array('one'=>__('hour'),'more'=>__('hours'), - 'zeros'=>true), - (60) => array('one'=>__('minute'),'more'=>__('minutes'), - 'zeros'=>true), - (1) => array('one'=>__('second'),'more'=>__('seconds'), - 'zeros'=>true), - ); - - foreach ($intervals as $k => $v) - { - if ($diff >= $k) - { - $time = floor($diff/$k); - $times[] = (($w->zeros AND $v['zeros']) - ? sprintf('%02d',$time) : $time).' '.(($time <= 1) ? $v['one'] - : $v['more']); - $diff = $diff%$k; - } - } - - # output - $text = ($after) ? $w->text_after : $w->text_before; - if (strlen($text) > 0) {$text .= ' ';} - - # get times and make a string - $times = array_slice($times,0,$w->number_of_times); - if (count($times) > 1) - { - $last = array_pop($times); - $str = implode(', ',$times).' '.__('and').' '.$last; - } - else {$str = implode('',$times);} - - if (!$w->dynamic) - { + $times = []; - $res = ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : ''). - '
'.$text.''.$str.'
'; - return $w->renderDiv($w->content_only,'countdown '.$w->class,'',$res); - } - - else - { - # dynamic display with Countdown for jQuery - if (!is_numeric(dcCore::app()->ctx->countdown)) - { - dcCore::app()->ctx->countdown = 0; - } - $id = dcCore::app()->ctx->countdown; - dcCore::app()->ctx->countdown += 1; - - $script = ''; - - if (!defined('COUNTDOWN_SCRIPT')) - { - $script = - ''."\n"; - - $l10n_file = - 'jquery.countdown-'.dcCore::app()->blog->settings->system->lang.'.js'; - if (file_exists(dirname(__FILE__).'/js/'.$l10n_file)) - { - $script .= - ''."\n"; - } - - define('COUNTDOWN_SCRIPT',(bool)true); - } - - if ($after) - { - $to = 'since'; - $layout = $w->dynamic_layout_after; - } - else - { - $to = 'until'; - $layout = $w->dynamic_layout_before; - } - - $res = ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : ''). - ''.$text.$str.'
'. - ''."\n"; - return $w->renderDiv($w->content_only,'countdown '.$w->class,'',$res); - } - } -} \ No newline at end of file + $intervals = [ + (3600 * 24 * 365.24) => ['one' => __('year'), 'more' => __('years'), 'zeros' => false], + (3600 * 24 * 30.4) => ['one' => __('month'), 'more' => __('months'), 'zeros' => false], + (3600 * 24) => ['one' => __('day'), 'more' => __('days'), 'zeros' => false], + (3600) => ['one' => __('hour'), 'more' => __('hours'), 'zeros' => true], + (60) => ['one' => __('minute'), 'more' => __('minutes'), 'zeros' => true], + (1) => ['one' => __('second'), 'more' => __('seconds'), 'zeros' => true], + ]; + + foreach ($intervals as $k => $v) { + if ($diff >= $k) { + $time = floor($diff / $k); + $times[] = (($w->zeros and $v['zeros']) + ? sprintf('%02d', $time) : $time) . ' ' . (($time <= 1) ? $v['one'] + : $v['more']); + $diff = $diff % $k; + } + } + + # output + $text = ($after) ? $w->text_after : $w->text_before; + if (strlen($text) > 0) { + $text .= ' '; + } + + # get times and make a string + $times = array_slice($times, 0, $w->number_of_times); + if (count($times) > 1) { + $last = array_pop($times); + $str = implode(', ', $times) . ' ' . __('and') . ' ' . $last; + } else { + $str = implode('', $times); + } + + if (!$w->dynamic) { + $res = ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') . + '' . $text . '' . $str . '
'; + + return $w->renderDiv($w->content_only, 'countdown ' . $w->class, '', $res); + } + + # dynamic display with Countdown for jQuery + if (!is_numeric(dcCore::app()->ctx->__get('countdown'))) { + dcCore::app()->ctx->__set('countdown', 0); + } + $id = (int) dcCore::app()->ctx->__get('countdown'); + dcCore::app()->ctx->__set('countdown', $id + 1); + + $script = ''; + + if (!defined('COUNTDOWN_SCRIPT')) { + $script .= dcUtils::cssLoad(dcCore::app()->blog->getPF(basename(__DIR__) . '/css/jquery.countdown.css')) . + dcUtils::jsLoad(dcCore::app()->blog->getPF(basename(__DIR__) . '/js/jquery.plugin.min.js')) . + dcUtils::jsLoad(dcCore::app()->blog->getPF(basename(__DIR__) . '/js/jquery.countdown.min.js')); + + $l10n_file = 'jquery.countdown-' . dcCore::app()->blog->settings->get('system')->get('lang') . '.js'; + if (file_exists(__DIR__ . '/js/' . $l10n_file)) { + $script .= dcUtils::jsLoad(dcCore::app()->blog->getPF(basename(__DIR__) . '/js/' . $l10n_file)); + } + + define('COUNTDOWN_SCRIPT', (bool) true); + } + + if ($after) { + $to = 'since'; + $layout = $w->dynamic_layout_after; + } else { + $to = 'until'; + $layout = $w->dynamic_layout_before; + } + + $res = ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') . + '' . $text . $str . '
' . + $script . + '' . "\n"; + + return $w->renderDiv($w->content_only, 'countdown ' . $w->class, '', $res); + } +} diff --git a/changelog b/changelog deleted file mode 100644 index 9759c2c..0000000 --- a/changelog +++ /dev/null @@ -1,7 +0,0 @@ -v1.6 - 28-12-2022 - Pierre Van Glabeke -* màj partielle dc2.24 - -v1.5 - 29-07-2016 - Pierre Van Glabeke -* mise à jour script jquery 1.6.3 -> 2.0.2 -* mise à jour pour compatibilité avec dc2.9 -* dc2.9 requis \ No newline at end of file diff --git a/dcstore.xml b/dcstore.xml new file mode 100644 index 0000000..115c743 --- /dev/null +++ b/dcstore.xml @@ -0,0 +1,13 @@ + +