3
* This file implements the Archives plugin.
5
* Displays a list of post archives.
7
* This file is part of the Quam Plures project - {@link http://quamplures.net/}
9
* @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
10
* @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}
11
* Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
13
* {@internal License choice
14
* - If you have received this file as part of a package, please find the license.txt file in
15
* the same folder or the closest folder above for complete license terms.
16
* - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
17
* then you must choose one of the following licenses before using the file:
18
* - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
19
* - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
22
* {@internal Open Source relicensing agreement:
23
* Daniel HAHLER grants Francois PLANQUE the right to license
24
* Daniel HAHLER's contributions to this file and the b2evolution project
25
* under any OSI approved OSS license (http://www.opensource.org/licenses/).
28
* {@internal Below is a list of authors who have contributed to design/coding of this file: }}
29
* @author blueyed: Daniel HAHLER.
30
* @author fplanque: Francois PLANQUE - {@link http://fplanque.net/}
3
* This file implements the Archives plugin
5
* @todo (2033) EdB> why does this have 2 title fields? one setting, one default setting...
7
* @author {@link http://wonderwinds.com/ Ed Bennett}
8
* @author {@link http://daniel.hahler.de/ Daniel HAHLER}
9
* @author {@link http://fplanque.net/ Francois PLANQUE}
31
10
* @author cafelog (group)
11
* @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
12
* @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
34
14
* @subpackage Archives
36
if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
38
load_class('_core/ui/results/_results.class.php');
16
if(!defined('QP_MAIN_INIT')) die('fail');
90
89
function TemplateTag( $params )
95
* @todo get rid of this global:
112
101
$params = array_merge( array(
113
// This is what will enclose the block in the template:
114
'block_start' => '<div class="bSideItem">',
115
'block_end' => "</div>\n",
117
'block_title_start' => '<h3>',
118
'block_title_end' => '</h3>',
120
'mode' => $Blog->get_setting('archive_mode'),
122
'link_type' => 'canonic',
123
'context_isolation' => 'm,w,p,title,unit,dstart',
126
// Number of archive entries to display:
129
'more_link' => $this->T_('More...'),
130
// This is what will enclose the list:
131
'list_start' => '<ul>',
132
'list_end' => "</ul>\n",
133
// This is what will separate the archive links:
134
'line_start' => '<li>',
135
'line_end' => "</li>\n",
136
'sort_order' => 'date',
137
// Daily archive date format?
138
'day_date_format' => locale_datefmt(),
102
'block_start' => '<div class="bSideItem">',
103
'block_end' => "</div>\n",
104
'block_title_start' => '<h3>',
105
'block_title_end' => '</h3>',
106
'mode' => $Blog->get_setting( 'archive_mode' ),
107
'link_type' => 'canonic',
108
'context_isolation' => 'm,w,p,title,unit,dstart',
111
'more_link' => $this->T_('More...'),
112
'list_start' => '<ul>',
113
'list_end' => "</ul>\n",
114
'line_start' => '<li>',
115
'line_end' => "</li>\n",
116
'sort_order' => 'date',
117
'day_date_format' => locale_datefmt(),
141
//Sort order (used only in postbypost mode):
142
if($params['mode'] !='postbypost' || $params['sort_order'] == ''){
120
// Sort order (used only in postbypost mode)
121
if( $params['mode'] !='postbypost' || $params['sort_order'] == '' )
143
123
$params['sort_order'] = 'date';
149
129
$params['day_date_format'] = locale_datefmt();
152
$ArchiveList = new ArchiveList( $params['mode'], $params['limit'], $params['sort_order'], ($params['link_type'] == 'context'),
153
$this->dbtable, $this->dbprefix, $this->dbIDname );
132
$ArchiveList = new ArchiveList(
133
$params['mode'], $params['limit'], $params['sort_order'],
134
( $params['link_type'] == 'context' ),
135
$this->dbtable, $this->dbprefix, $this->dbIDname );
155
137
echo $params['block_start'];
157
if( !empty($params['title']) )
158
{ // We want to display a title for the widget block:
139
if( ! empty( $params['title'] ) )
141
// We want to display a title for the widget block
159
142
echo $params['block_title_start'];
160
143
echo $params['title'];
161
144
echo $params['block_title_end'];
164
147
echo $params['list_start'];
165
while( $ArchiveList->get_item( $arc_year, $arc_month, $arc_dayofmonth, $arc_w, $arc_count, $post_ID, $post_title) )
148
while( $ArchiveList->get_item( $arc_year, $arc_month, $arc_dayofmonth, $arc_w, $arc_count, $post_ID, $post_title ) )
167
150
echo $params['line_start'];
168
151
switch( $params['mode'] )
171
// --------------------------------- MONTHLY ARCHIVES -------------------------------------
172
$arc_m = $arc_year.zeroise($arc_month,2);
174
if( $params['form'] )
175
{ // We want a radio button:
176
echo '<input type="radio" name="m" value="'.$arc_m.'" class="checkbox"';
177
if( $m == $arc_m ) echo ' checked="checked"' ;
181
$text = $this->T_($month[zeroise($arc_month,2)]).' '.$arc_year;
183
if( $params['link_type'] == 'context' )
184
{ // We want to preserve current browsing context:
185
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'm='.$arc_m ).'">'.$text.'</a>';
188
{ // We want to link to the absolute canonical URL for this archive:
189
echo $Blog->gen_archive_link( $text, $this->T_('View monthly archive'), $arc_year, $arc_month );
192
echo ' <span class="dimmed">('.$arc_count.')</span>';
154
$arc_m = $arc_year.zeroise( $arc_month, 2 );
155
if( $params['form'] )
157
// We want a radio button
158
echo '<input type="radio" name="m" value="'.$arc_m.'" class="checkbox"';
159
if( $m == $arc_m ) echo ' checked="checked"' ;
162
$text = $this->T_( $month[zeroise( $arc_month,2 )] ).' '.$arc_year;
163
if( $params['link_type'] == 'context' )
165
// We want to preserve current browsing context
166
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'm='.$arc_m ).'">'.$text.'</a>';
170
// We want to link to the absolute canonical URL for this archive
171
echo $Blog->gen_archive_link( $text, $this->T_('View monthly archive'), $arc_year, $arc_month );
173
echo ' <span class="dimmed">('.$arc_count.')</span>';
196
// --------------------------------- DAILY ARCHIVES ---------------------------------------
197
$arc_m = $arc_year.zeroise($arc_month,2).zeroise($arc_dayofmonth,2);
199
if( $params['form'] )
200
{ // We want a radio button:
201
echo '<input type="radio" name="m" value="'. $arc_m. '" class="checkbox"';
202
if( $m == $arc_m ) echo ' checked="checked"' ;
206
$text = mysql2date($params['day_date_format'], $arc_year.'-'.zeroise($arc_month,2).'-'.zeroise($arc_dayofmonth,2).' 00:00:00');
208
if( $params['link_type'] == 'context' )
209
{ // We want to preserve current browsing context:
210
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'm='.$arc_m ).'">'.$text.'</a>';
213
{ // We want to link to the absolute canonical URL for this archive:
214
echo $Blog->gen_archive_link( $text, $this->T_('View daily archive'), $arc_year, $arc_month, $arc_dayofmonth );
217
echo ' <span class="dimmed">('.$arc_count.')</span>';
177
$arc_m = $arc_year.zeroise( $arc_month, 2 ).zeroise( $arc_dayofmonth, 2 );
178
if( $params['form'] )
180
// We want a radio button
181
echo '<input type="radio" name="m" value="'. $arc_m. '" class="checkbox"';
182
if( $m == $arc_m ) echo ' checked="checked"' ;
185
$text = mysql2date( $params['day_date_format'], $arc_year.'-'.zeroise( $arc_month, 2 ).'-'.zeroise( $arc_dayofmonth, 2 ).' 00:00:00');
186
if( $params['link_type'] == 'context' )
187
{ // We want to preserve current browsing context
188
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'm='.$arc_m ).'">'.$text.'</a>';
192
// We want to link to the absolute canonical URL for this archive
193
echo $Blog->gen_archive_link( $text, $this->T_('View daily archive'), $arc_year, $arc_month, $arc_dayofmonth );
195
echo ' <span class="dimmed">('.$arc_count.')</span>';
221
// --------------------------------- WEEKLY ARCHIVES --------------------------------------
223
$text = $arc_year.', '.$this->T_('week').' '.$arc_w;
225
if( $params['link_type'] == 'context' )
226
{ // We want to preserve current browsing context:
227
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'm='.$arc_year.'&w='.$arc_w ).'">'.$text.'</a>';
230
{ // We want to link to the absolute canonical URL for this archive:
231
echo $Blog->gen_archive_link( $text, $this->T_('View weekly archive'), $arc_year, NULL, NULL, $arc_w );
233
echo ' <span class="dimmed">('.$arc_count.')</span>';
199
$text = $arc_year.', '.$this->T_('week').' '.$arc_w;
200
if( $params['link_type'] == 'context' )
202
// We want to preserve current browsing context
203
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'm='.$arc_year.'&w='.$arc_w ).'">'.$text.'</a>';
207
// We want to link to the absolute canonical URL for this archive
208
echo $Blog->gen_archive_link( $text, $this->T_('View weekly archive'), $arc_year, NULL, NULL, $arc_w );
210
echo ' <span class="dimmed">('.$arc_count.')</span>';
236
213
case 'postbypost':
238
// -------------------------------- POST BY POST ARCHIVES ---------------------------------
242
$text = strip_tags($post_title);
249
if( $params['link_type'] == 'context' )
250
{ // We want to preserve current browsing context:
251
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'p='.$post_ID ).'">'.$text.'</a>';
254
{ // We want to link to the absolute (canonical) URL for this archive:
255
// fp> TODO: This is NOT canonical. To go to the canonical, we'd need a 'light' itemlist (which does not load too much data)
256
// fp> Note: there may be a "redirect to canonical" anyway. Not optimal, but at least this is less broken than it was before.
257
// fp> THIS IS ALL OBSOLETE. There is a better way to have a post list with a specific widget.
258
// TO BE DELETED (waiting for photoblog cleanup)
259
echo '<a href="'.url_add_param( $Blog->get('url'), 'p='.$post_ID.'&more=1&c=1&tb=1' ).'">'.$text.'</a>';
217
$text = strip_tags( $post_title );
224
if( $params['link_type'] == 'context' )
226
// We want to preserve current browsing context
227
echo '<a rel="nofollow" href="'.regenerate_url( $params['context_isolation'], 'p='.$post_ID ).'">'.$text.'</a>';
231
// We want to link to the absolute (canonical) URL for this archive:
232
// @todo (0000) fp> This is NOT canonical. To go to the canonical, we'd
233
// need a 'light' itemlist (which does not load too much data)
234
// fp> Note: there may be a "redirect to canonical" anyway. Not optimal,
235
// but at least this is less broken than it was before.
236
// fp> THIS IS ALL OBSOLETE. There is a better way to have a post list
237
// with a specific widget. TO BE DELETED (waiting for photoblog cleanup)
238
echo '<a href="'.url_add_param( $Blog->get( 'url' ), 'p='.$post_ID.'&more=1&c=1&tb=1' ).'">'.$text.'</a>';
263
242
echo $params['line_end'];
266
// Display more link:
267
if( !empty($params['more_link']) )
246
if( ! empty( $params['more_link'] ) )
269
248
echo $params['line_start'];
270
249
echo '<a href="';
271
250
$Blog->disp( 'arcdirurl', 'raw' );
272
echo '">'.format_to_output($params['more_link']).'</a>';
251
echo '">'.format_to_output( $params['more_link'] ).'</a>';
273
252
echo $params['line_end'];
276
255
echo $params['list_end'];
278
256
echo $params['block_end'];
285
* @see Plugin::GetDefaultWidgetSettings()
287
function GetDefaultWidgetSettings( $params )
291
'label' => $this->T_('Block title'),
292
'note' => $this->T_('Title to display in your template.'),
294
'defaultvalue' => $this->T_('Archives'),
297
'label' => $this->T_('Max items'),
298
'note' => $this->T_('Maximum number of items to display.'),
300
'defaultvalue' => 12,
312
266
* @package plugins
267
* @subpackage Archives
314
269
class ArchiveList extends Results
341
295
$dbprefix = 'post_',
342
296
$dbIDname = 'ID' )
345
global $blog, $cat, $catsel;
346
307
global $show_statuses;
347
global $author, $assgn, $status, $types;
348
global $timestamp_min, $timestamp_max;
349
global $s, $sentence, $exact;
310
global $timestamp_min;
311
global $timestamp_max;
351
313
$this->dbtable = $dbtable;
352
314
$this->dbprefix = $dbprefix;
353
315
$this->dbIDname = $dbIDname;
354
316
$this->archive_mode = $archive_mode;
358
* WE ARE GOING TO CONSTRUCT THE WHERE CLOSE...
318
// WE ARE GOING TO CONSTRUCT THE WHERE CLOSE...
360
319
$this->ItemQuery = new ItemQuery( $this->dbtable, $this->dbprefix, $this->dbIDname ); // TEMPORARY OBJ
362
// - - Select a specific Item:
321
// - - Select a specific Item
363
322
// $this->ItemQuery->where_ID( $p, $title );
365
324
if( $preserve_context )
366
{ // We want to preserve the current context:
367
// * - - Restrict to selected blog/categories:
368
$this->ItemQuery->where_chapter( $blog, $cat, $catsel );
370
// * Restrict to the statuses we want to show:
326
// We want to preserve the current context
327
// * - - Restrict to selected blog/categories
328
$this->ItemQuery->where_category( $blog, $cat, $catsel );
329
// * Restrict to the statuses we want to show
371
330
$this->ItemQuery->where_visibility( $show_statuses );
373
// Restrict to selected authors:
331
// Restrict to selected authors
374
332
$this->ItemQuery->where_author( $author );
376
// Restrict to selected assignees:
333
// Restrict to selected assignees
377
334
$this->ItemQuery->where_assignees( $assgn );
379
// Restrict to selected satuses:
335
// Restrict to selected satuses
380
336
$this->ItemQuery->where_statuses( $status );
382
// - - - + * * timestamp restrictions:
337
// - - - + * * timestamp restrictions
383
338
$this->ItemQuery->where_datestart( '', '', '', '', $timestamp_min, $timestamp_max );
385
// Keyword search stuff:
339
// Keyword search stuff
386
340
$this->ItemQuery->where_keywords( $s, $sentence, $exact );
388
341
$this->ItemQuery->where_types( $types );
391
{ // We want to preserve only the minimal context:
392
// * - - Restrict to selected blog/categories:
393
$this->ItemQuery->where_chapter( $blog, '', array() );
395
// * Restrict to the statuses we want to show:
345
// We want to preserve only the minimal context
346
// * - - Restrict to selected blog/categories
347
$this->ItemQuery->where_category( $blog, '', array() );
348
// * Restrict to the statuses we want to show
396
349
$this->ItemQuery->where_visibility( $show_statuses );
398
// - - - + * * timestamp restrictions:
350
// - - - + * * timestamp restrictions
399
351
$this->ItemQuery->where_datestart( '', '', '', '', $timestamp_min, $timestamp_max );
401
// Include all types except pages, intros and sidebar links:
402
$this->ItemQuery->where_types( '-1000,1500,1520,1530,1570,1600,3000' );
352
// Include all types except pages, intros and sidebar links
353
$this->ItemQuery->where_types( '-1000,1500,1520,1530,1570,2000' );
406
356
$this->from = $this->ItemQuery->get_from();
407
357
$this->where = $this->ItemQuery->get_where();
408
358
$this->group_by = $this->ItemQuery->get_group_by();
410
360
switch( $this->archive_mode )
413
// ------------------------------ MONTHLY ARCHIVES ------------------------------------
414
$sql = 'SELECT EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) AS year, EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) AS month,
415
COUNT(DISTINCT postcat_post_ID) AS count '
419
ORDER BY year DESC, month DESC';
363
$sql = 'SELECT EXTRACT(YEAR FROM '
364
.$this->dbprefix.'datestart) AS year, EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) AS month,
365
COUNT(DISTINCT postcat_post_ID) AS count '
369
ORDER BY year DESC, month DESC';
423
// ------------------------------- DAILY ARCHIVES -------------------------------------
424
$sql = 'SELECT EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) AS year, MONTH('.$this->dbprefix.'datestart) AS month,
425
DAYOFMONTH('.$this->dbprefix.'datestart) AS day,
426
COUNT(DISTINCT postcat_post_ID) AS count '
429
GROUP BY year, month, day
430
ORDER BY year DESC, month DESC, day DESC';
373
$sql = 'SELECT EXTRACT(YEAR FROM '
374
.$this->dbprefix.'datestart) AS year, MONTH('.$this->dbprefix.'datestart) AS month,
375
DAYOFMONTH('.$this->dbprefix.'datestart) AS day,
376
COUNT(DISTINCT postcat_post_ID) AS count '
379
GROUP BY year, month, day
380
ORDER BY year DESC, month DESC, day DESC';
434
// ------------------------------- WEEKLY ARCHIVES -------------------------------------
435
$sql = 'SELECT EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) AS year, '.
436
$DB->week( $this->dbprefix.'datestart', locale_startofweek() ).' AS week,
437
COUNT(DISTINCT postcat_post_ID) AS count '
441
ORDER BY year DESC, week DESC';
384
$sql = 'SELECT EXTRACT(YEAR FROM '
385
.$this->dbprefix.'datestart) AS year, '.
386
$DB->week( $this->dbprefix.'datestart', locale_startofweek() ).' AS week,
387
COUNT(DISTINCT postcat_post_ID) AS count '
391
ORDER BY year DESC, week DESC';
444
394
case 'postbypost':
446
// ----------------------------- POSY BY POST ARCHIVES --------------------------------
447
$sql = 'SELECT DISTINCT '.$this->dbIDname.', '.$this->dbprefix.'datestart, '.$this->dbprefix.'title '
452
if($sort_order == 'title'){
453
$sql .= $this->dbprefix.'title ASC';
455
else if($sort_order == 'date'){
456
$sql .= $this->dbprefix.'datestart DESC';
396
$sql = 'SELECT DISTINCT '.
397
$this->dbIDname.', '.$this->dbprefix.'datestart, '.$this->dbprefix.'title '
402
if( $sort_order == 'title' )
404
$sql .= $this->dbprefix.'title ASC';
406
elseif( $sort_order == 'date' )
408
$sql .= $this->dbprefix.'datestart DESC';
461
413
// dh> Temp fix for MySQL bug - apparently in/around 4.1.21/5.0.24.
462
// See http://forums.b2evolution.net/viewtopic.php?p=42529#42529
463
if( in_array($this->archive_mode, array('monthly', 'daily', 'weekly')) )
414
if( in_array( $this->archive_mode, array( 'monthly', 'daily', 'weekly' ) ) )
465
416
$sql_version = $DB->get_var('SELECT VERSION()'); // fp> TODO: $DB->get_mysql_version()
466
if( version_compare($sql_version, '4', '>') )
417
if( version_compare( $sql_version, '4', '>' ) )
468
419
$sql = 'SELECT SQL_CALC_FOUND_ROWS '.substr( $sql, 7 ); // "SQL_CALC_FOUND_ROWS" available since MySQL 4
473
423
parent::Results( $sql, 'archivelist_', '', $limit );
475
425
$this->restart();