2 // PukiWiki - Yet another WikiWikiWeb clone
3 // calendar_viewer.inc.php
4 // Copyright 2002-2021 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
7 // Calendar viewer plugin - List pages that calendar/calnedar2 plugin created
8 // (Based on calendar and recent plugin)
10 // Page title's date format
11 // * See PHP date() manual for detail
12 // * '$\w' = weeklabel defined in $_msg_week
13 define('PLUGIN_CALENDAR_VIEWER_DATE_FORMAT',
14 // FALSE // 'pagename/2004-02-09' -- As is
15 // 'D, d M, Y' // 'Mon, 09 Feb, 2004'
16 // 'F d, Y' // 'February 09, 2004'
17 // '[Y-m-d]' // '[2004-02-09]'
18 'Y/n/j ($\w)' // '2004/2/9 (Mon)'
21 * Limit of show count per pagename
23 define('PLUGIN_CALENDAR_VIEWER_MAX_SHOW_COUNT', 4);
27 define('PLUGIN_CALENDAR_VIEWER_USAGE',
28 '#calendar_viewer(pagename,this|yyyy-mm|n|x*y[,mode[,separater]])');
31 * - A working root of calendar or calendar2 plugin
37 * this - Show 'this month'
38 * yyyy-mm - Show pages at year:yyyy and month:mm
39 * n - Show first n pages
40 * x*n - Show first n pages from x-th page (0 = first)
43 * past - Show today, and the past below. Recommended for ChangeLogs and diaries (default)
44 * future - Show today, and the future below. Recommended for event planning and scheduling
45 * view - Show all, from the past to the future
48 * - Specify separator of yyyy/mm/dd
49 * - Default: '-' (yyyy-mm-dd)
52 * Stop showing links 'next month' and 'previous month' with past/future mode for 'this month'
53 * #calendar_viewer(pagename,this,past)
56 function plugin_calendar_viewer_convert()
58 global $vars, $get, $post, $weeklabels;
59 global $_msg_calendar_viewer_right, $_msg_calendar_viewer_left;
60 global $_msg_calendar_viewer_restrict, $_err_calendar_viewer_param2;
62 static $show_count = array();
64 if (func_num_args() < 2)
65 return PLUGIN_CALENDAR_VIEWER_USAGE . '<br />' . "\n";
67 $func_args = func_get_args();
70 $pagename = $func_args[0]; // 基準となるページ名
71 $page_YM = ''; // 一覧表示する年月
72 $limit_base = 0; // 先頭から数えて何ページ目から表示するか (先頭)
73 $limit_pitch = 0; // 何件づつ表示するか
74 $limit_page = 0; // サーチするページ数
75 $mode = 'past'; // 動作モード
76 $date_sep = '-'; // 日付のセパレータ calendar2なら '-', calendarなら ''
78 // Check $func_args[1]
80 if (preg_match('/[0-9]{4}' . $date_sep . '[0-9]{2}/', $func_args[1])) {
82 $page_YM = $func_args[1];
84 } else if (preg_match('/this/si', $func_args[1])) {
86 $page_YM = get_date('Y' . $date_sep . 'm');
88 } else if (preg_match('/^[0-9]+$/', $func_args[1])) {
90 $limit_pitch = $func_args[1];
91 $limit_page = $func_args[1];
92 } else if (preg_match('/(-?[0-9]+)\*([0-9]+)/', $func_args[1], $matches)) {
93 // 先頭より数えて x ページ目から、y件づつ表示
94 $limit_base = $matches[1];
95 $limit_pitch = $matches[2];
96 $limit_page = $matches[1] + $matches[2]; // 読み飛ばす + 表示する
98 return '#calendar_viewer(): ' . $_err_calendar_viewer_param2 . '<br />' . "\n";
101 // $func_args[2]: Mode setting
102 if (isset($func_args[2]) && preg_match('/^(past|view|future)$/si', $func_args[2]))
103 $mode = $func_args[2];
105 // $func_args[3]: Change default delimiter
106 if (isset($func_args[3])) $date_sep = $func_args[3];
109 if (!isset($show_count[$pagename])) {
110 $show_count[$pagename] = 0;
112 $show_count[$pagename] += 1;
113 if ($show_count[$pagename] > PLUGIN_CALENDAR_VIEWER_MAX_SHOW_COUNT) {
114 $s_page = htmlsc($pagename);
115 return "#calendar_viewer(): Exceeded the limit of show count: $s_page<br />";
118 $simple_pagename = strip_bracket($pagename);
119 if ($pagename === '') {
120 // Support non-pagename yyyy-mm-dd pattern
121 $pagepattern = $page_YM;
122 $page_datestart_idx = 0;
124 $pagepattern = $simple_pagename . '/' . $page_YM;
125 $page_datestart_idx = strlen($simple_pagename) + 1;
127 $pagepattern_len = strlen($pagepattern);
130 $_date = get_date('Y' . $date_sep . 'm' . $date_sep . 'd');
131 foreach (get_existpages() as $page) {
132 if (strncmp($page, $pagepattern, $pagepattern_len) !== 0) continue;
133 $page_date = substr($page, $page_datestart_idx);
134 // Verify the $page_date pattern (Default: yyyy-mm-dd).
135 // Past-mode hates the future, and
136 // Future-mode hates the past.
137 if ((plugin_calendar_viewer_isValidDate($page_date, $date_sep) === FALSE) ||
138 ($page_date > $_date && ($mode === 'past')) ||
139 ($page_date < $_date && ($mode === 'future'))) {
144 if ($mode == 'past') {
145 rsort($pagelist, SORT_STRING); // New => Old
147 sort($pagelist, SORT_STRING); // Old => New
150 $tmppage = $vars['page'];
153 // $limit_page の件数までインクルード
154 $tmp = max($limit_base, 0); // Skip minus
155 while ($tmp < $limit_page) {
156 if (! isset($pagelist[$tmp])) break;
158 $page = $pagelist[$tmp];
159 $get['page'] = $post['page'] = $vars['page'] = $page;
161 // 現状で閲覧許可がある場合だけ表示する
162 if (check_readable($page, FALSE, FALSE)) {
163 $body = convert_html(get_source($page));
165 $body = str_replace('$1', $page, $_msg_calendar_viewer_restrict);
167 if (PLUGIN_CALENDAR_VIEWER_DATE_FORMAT !== FALSE) {
168 $time = strtotime(basename($page)); // $date_sep must be assumed '-' or ''!
169 if ($time === FALSE || $time === -1) {
170 $s_page = htmlsc($page); // Failed. Why?
172 $week = $weeklabels[date('w', $time)];
173 $s_page = htmlsc(str_replace(
176 date(PLUGIN_CALENDAR_VIEWER_DATE_FORMAT, $time)
180 $s_page = htmlsc($page);
184 $link = get_page_uri($page);
186 $link = get_base_uri() . '?cmd=edit&page=' . pagename_urlencode($page);
188 $link_html = '<a href="' . $link . '">' . $s_page . '</a>';
189 $head = '<h1>' . $link_html . '</h1>' . "\n";
190 $return_body .= $head . $body;
195 // ?plugin=calendar_viewer&file=ページ名&date=yyyy-mm
196 if ($page_YM != '') {
198 $date_sep_len = strlen($date_sep);
199 $this_year = substr($page_YM, 0, 4);
200 $this_month = substr($page_YM, 4 + $date_sep_len, 2);
203 $next_year = $this_year;
204 $next_month = $this_month + 1;
205 if ($next_month > 12) {
209 $next_YM = sprintf('%04d%s%02d', $next_year, $date_sep, $next_month);
212 $prev_year = $this_year;
213 $prev_month = $this_month - 1;
214 if ($prev_month < 1) {
218 $prev_YM = sprintf('%04d%s%02d', $prev_year, $date_sep, $prev_month);
219 if ($mode == 'past') {
220 $right_YM = $prev_YM;
221 $right_text = $prev_YM . '>>'; // >>
223 $left_text = '<<' . $next_YM; // <<
226 $left_text = '<<' . $prev_YM; // <<
227 $right_YM = $next_YM;
228 $right_text = $next_YM . '>>'; // >>
232 if ($limit_base <= 0) {
233 $left_YM = ''; // 表示しない (それより前の項目はない)
235 $left_YM = $limit_base - $limit_pitch . '*' . $limit_pitch;
236 $left_text = sprintf($_msg_calendar_viewer_left, $limit_pitch);
239 if ($limit_base + $limit_pitch >= count($pagelist)) {
240 $right_YM = ''; // 表示しない (それより後の項目はない)
242 $right_YM = $limit_base + $limit_pitch . '*' . $limit_pitch;
243 $right_text = sprintf($_msg_calendar_viewer_right, $limit_pitch);
248 if ($left_YM != '' || $right_YM != '') {
249 $s_date_sep = htmlsc($date_sep);
250 $left_link = $right_link = '';
251 $link = get_base_uri() . '?plugin=calendar_viewer&mode=' . $mode .
252 '&file=' . rawurlencode($simple_pagename) .
253 '&date_sep=' . $s_date_sep . '&';
255 $left_link = '<a href="' . $link .
256 'date=' . $left_YM . '">' . $left_text . '</a>';
258 $right_link = '<a href="' . $link .
259 'date=' . $right_YM . '">' . $right_text . '</a>';
260 // past modeは<<新 旧>> 他は<<旧 新>>
262 '<div class="calendar_viewer">' .
263 '<span class="calendar_viewer_left">' . $left_link . '</span>' .
264 '<span class="calendar_viewer_right">' . $right_link . '</span>' .
268 $get['page'] = $post['page'] = $vars['page'] = $tmppage;
273 function plugin_calendar_viewer_action()
275 global $vars, $get, $post;
279 $return_vars_array = array();
281 $page = strip_bracket($vars['page']);
283 if (isset($vars['file'])) $vars['page'] = $vars['file'];
285 $date_sep = $vars['date_sep'];
287 $page_YM = $vars['date'];
288 if ($page_YM == '') $page_YM = get_date('Y' . $date_sep . 'm');
289 $mode = $vars['mode'];
291 $args_array = array($vars['page'], $page_YM, $mode, $date_sep);
292 $return_vars_array['body'] = call_user_func_array('plugin_calendar_viewer_convert', $args_array);
294 //$return_vars_array['msg'] = 'calendar_viewer ' . $vars['page'] . '/' . $page_YM;
295 $return_vars_array['msg'] = 'calendar_viewer ' . htmlsc($vars['page']);
296 if ($vars['page'] != '') $return_vars_array['msg'] .= '/';
297 if (preg_match('/\*/', $page_YM)) {
298 // うーん、n件表示の時はなんてページ名にしたらいい?
300 $return_vars_array['msg'] .= htmlsc($page_YM);
303 $vars['page'] = $page;
304 return $return_vars_array;
307 function plugin_calendar_viewer_isValidDate($aStr, $aSepList = '-/ .')
310 if ($aSepList == '') {
311 // yyymmddとしてチェック(手抜き(^^;)
312 return checkdate(substr($aStr, 4, 2), substr($aStr, 6, 2), substr($aStr, 0, 4));
313 } else if (preg_match("#^([0-9]{2,4})[$aSepList]([0-9]{1,2})[$aSepList]([0-9]{1,2})$#", $aStr, $matches) ) {
314 return checkdate($matches[2], $matches[3], $matches[1]);