| [ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements the Calendar plugin. 4 * 5 * This file is part of the b2evolution project - {@link http://b2evolution.net/} 6 * 7 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/} 8 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}. 9 * 10 * {@internal License choice 11 * - If you have received this file as part of a package, please find the license.txt file in 12 * the same folder or the closest folder above for complete license terms. 13 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 14 * then you must choose one of the following licenses before using the file: 15 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 16 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 17 * }} 18 * 19 * {@internal Open Source relicensing agreement: 20 * Daniel HAHLER grants Francois PLANQUE the right to license 21 * Daniel HAHLER's contributions to this file and the b2evolution project 22 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 23 * }} 24 * 25 * @package plugins 26 * 27 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 28 * @author blueyed: Daniel HAHLER. 29 * @author fplanque: Francois PLANQUE - {@link http://fplanque.net/} 30 * @author hansreinders: Hans REINDERS 31 * @author cafelog (team) 32 * 33 * @version $Id: _calendar.plugin.php,v 1.46 2007/10/09 02:10:50 fplanque Exp $ 34 */ 35 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 36 37 38 /** 39 * Calendar Plugin 40 * 41 * This plugin displays 42 */ 43 class calendar_plugin extends Plugin 44 { 45 /** 46 * Variables below MUST be overriden by plugin implementations, 47 * either in the subclass declaration or in the subclass constructor. 48 */ 49 50 var $name = 'Calendar Widget'; 51 var $code = 'evo_Calr'; 52 var $priority = 20; 53 var $version = '2.0'; 54 var $author = 'The b2evo Group'; 55 var $group = 'widget'; 56 57 58 /** 59 * @var ItemQuery 60 */ 61 var $ItemQuery; 62 63 /** 64 * Init 65 */ 66 function PluginInit( & $params ) 67 { 68 $this->short_desc = T_('This skin tag displays a navigable calendar.'); 69 $this->long_desc = T_('Days containing posts are highlighted.'); 70 71 $this->dbtable = 'T_items__item'; 72 $this->dbprefix = 'post_'; 73 $this->dbIDname = 'post_ID'; 74 } 75 76 77 /** 78 * Get definitions for widget specific editable params 79 * 80 * @see Plugin::GetDefaultSettings() 81 * @param local params like 'for_editing' => true 82 */ 83 function get_widget_param_definitions( $params ) 84 { 85 $r = array( 86 'displaycaption' => array( 87 'label' => T_('Display caption'), 88 'note' => T_('Display caption on top of calendar'), 89 'type' => 'checkbox', 90 'defaultvalue' => true, 91 ), 92 'linktomontharchive' => array( 93 'label' => T_('Link caption to archives'), 94 'note' => T_('The month in the caption can be clicked to see all posts for this month'), 95 'type' => 'checkbox', 96 'defaultvalue' => true, 97 ), 98 'headerdisplay' => array( 99 'label' => 'Column headers', 100 'note' => T_('How do you want to display the days of the week in the column headers?'), 101 'type' => 'select', 102 'options' => array( 'e' => 'F', 'D' => 'Fri', 'l' => 'Friday', '' => T_('No header') ), 103 'defaultvalue' => 'D', 104 ), 105 'navigation' => array( 106 'label' => 'Navigation arrows', 107 'note' => T_('Where do you want to display the navigation arrows?'), 108 'type' => 'select', 109 'options' => array( 'caption' => T_('Top'), 'tfoot' => T_('Bottom'), '' => T_('No navigation') ), 110 'defaultvalue' => 'tfoot', 111 ), 112 'navigation' => array( 113 'label' => 'Navigation arrows', 114 'note' => T_('Where do you want to display the navigation arrows?'), 115 'type' => 'select', 116 'options' => array( 'caption' => T_('Top'), 'tfoot' => T_('Bottom'), '' => T_('No navigation') ), 117 'defaultvalue' => 'tfoot', 118 ), 119 'browseyears' => array( 120 'label' => T_('Navigate years'), 121 'note' => T_('Display double arrows for yearly navigation?'), 122 'type' => 'checkbox', 123 'defaultvalue' => true, 124 ), 125 ); 126 return $r; 127 } 128 129 130 /** 131 * Event handler: SkinTag (widget) 132 * 133 * @param array Associative array of parameters. Valid keys are: 134 * - 'block_start' : (Default: '<div class="bSideItem">') 135 * - 'block_end' : (Default: '</div>') 136 * - 'title' : (Default: T_('Calendar')) 137 * - 'displaycaption' 138 * - 'monthformat' 139 * - 'linktomontharchive' 140 * - 'tablestart' 141 * - 'tableend' 142 * - 'monthstart' 143 * - 'monthend' 144 * - 'rowstart' 145 * - 'rowend' 146 * - 'headerdisplay' 147 * - 'headerrowstart' 148 * - 'headerrowend' 149 * - 'headercellstart' 150 * - 'headercellend' 151 * - 'cellstart' 152 * - 'cellend' 153 * - 'linkpostcellstart' 154 * - 'linkposttodaycellstart' 155 * - 'todaycellstart' 156 * - 'todaycellstartpost' 157 * - 'navigation' : Where do we want to have the navigation arrows? (Default: 'tfoot') 158 * - 'browseyears' : boolean Do we want arrows to move one year at a time? 159 * - 'min_timestamp' : Minimum unix timestamp the user can browse too or 'query' (Default: 2000-01-01) 160 * - 'max_timestamp' : Maximum unix timestamp the user can browse too or 'query' (Default: now + 1 year ) 161 * - 'postcount_month_cell' 162 * - 'postcount_month_cell_one' 163 * - 'postcount_month_atitle' 164 * - 'postcount_month_atitle_one' 165 * - 'postcount_year_cell' 166 * - 'postcount_year_cell_one' 167 * - 'postcount_year_atitle' 168 * - 'postcount_year_atitle_one' 169 * - 'link_type' : 'canonic'|'context' (default: canonic) 170 * @return boolean did we display? 171 */ 172 function SkinTag( $params ) 173 { 174 global $Settings, $month; 175 global $Blog, $cat_array, $cat_modifier; 176 global $show_statuses; 177 global $author, $assgn, $status; 178 global $m, $w, $dstart, $timestamp_min, $timestamp_max; 179 global $s, $sentence, $exact; 180 181 /** 182 * Default params: 183 */ 184 // This is what will enclose the block in the skin: 185 if(!isset($params['block_start'])) $params['block_start'] = '<div class="bSideItem">'; 186 if(!isset($params['block_end'])) $params['block_end'] = "</div>\n"; 187 188 // Title: 189 if(!isset($params['block_title_start'])) $params['block_title_start'] = '<h3>'; 190 if(!isset($params['block_title_end'])) $params['block_title_end'] = '</h3>'; 191 if(!isset($params['title'])) $params['title'] = ''; 192 193 194 $Calendar = & new Calendar( $m, $params ); 195 196 // TODO: automate with a table inside of Calendatr object. Table should also contain descriptions and default values to display in help screen. 197 // Note: minbrowse and maxbrowe already work this way. 198 if( isset($params['displaycaption']) ) $Calendar->set( 'displaycaption', $params['displaycaption'] ); 199 if( isset($params['monthformat']) ) $Calendar->set( 'monthformat', $params['monthformat'] ); 200 if( isset($params['linktomontharchive']) ) $Calendar->set( 'linktomontharchive', $params['linktomontharchive'] ); 201 if( isset($params['tablestart']) ) $Calendar->set( 'tablestart', $params['tablestart'] ); 202 if( isset($params['tableend']) ) $Calendar->set( 'tableend', $params['tableend'] ); 203 if( isset($params['monthstart']) ) $Calendar->set( 'monthstart', $params['monthstart'] ); 204 if( isset($params['monthend']) ) $Calendar->set( 'monthend', $params['monthend'] ); 205 if( isset($params['rowstart']) ) $Calendar->set( 'rowstart', $params['rowstart'] ); 206 if( isset($params['rowend']) ) $Calendar->set( 'rowend', $params['rowend'] ); 207 if( isset($params['headerdisplay']) ) $Calendar->set( 'headerdisplay', $params['headerdisplay'] ); 208 if( isset($params['headerrowstart']) ) $Calendar->set( 'headerrowstart', $params['headerrowstart'] ); 209 if( isset($params['headerrowend']) ) $Calendar->set( 'headerrowend', $params['headerrowend'] ); 210 if( isset($params['headercellstart']) ) $Calendar->set( 'headercellstart', $params['headercellstart'] ); 211 if( isset($params['headercellend']) ) $Calendar->set( 'headercellend', $params['headercellend'] ); 212 if( isset($params['cellstart']) ) $Calendar->set( 'cellstart', $params['cellstart'] ); 213 if( isset($params['cellend']) ) $Calendar->set( 'cellend', $params['cellend'] ); 214 if( isset($params['emptycellstart']) ) $Calendar->set( 'emptycellstart', $params['emptycellstart'] ); 215 if( isset($params['emptycellend']) ) $Calendar->set( 'emptycellend', $params['emptycellend'] ); 216 if( isset($params['emptycellcontent']) ) $Calendar->set( 'emptycellcontent', $params['emptycellcontent'] ); 217 if( isset($params['linkpostcellstart']) ) $Calendar->set( 'linkpostcellstart', $params['linkpostcellstart'] ); 218 if( isset($params['linkposttodaycellstart']) ) $Calendar->set( 'linkposttodaycellstart', $params['linkposttodaycellstart'] ); 219 if( isset($params['todaycellstart']) ) $Calendar->set( 'todaycellstart', $params['todaycellstart'] ); 220 if( isset($params['todaycellstartpost']) ) $Calendar->set( 'todaycellstartpost', $params['todaycellstartpost'] ); 221 if( isset($params['navigation']) ) $Calendar->set( 'navigation', $params['navigation'] ); 222 if( isset($params['browseyears']) ) $Calendar->set( 'browseyears', $params['browseyears'] ); 223 if( isset($params['postcount_month_cell']) ) $Calendar->set( 'postcount_month_cell', $params['postcount_month_cell'] ); 224 if( isset($params['postcount_month_cell_one']) ) $Calendar->set( 'postcount_month_cell_one', $params['postcount_month_cell_one'] ); 225 if( isset($params['postcount_month_atitle']) ) $Calendar->set( 'postcount_month_atitle', $params['postcount_month_atitle'] ); 226 if( isset($params['postcount_month_atitle_one']) ) $Calendar->set( 'postcount_month_atitle_one', $params['postcount_month_atitle_one'] ); 227 if( isset($params['postcount_year_cell']) ) $Calendar->set( 'postcount_year_cell', $params['postcount_year_cell'] ); 228 if( isset($params['postcount_year_cell_one']) ) $Calendar->set( 'postcount_year_cell_one', $params['postcount_year_cell_one'] ); 229 if( isset($params['postcount_year_atitle']) ) $Calendar->set( 'postcount_year_atitle', $params['postcount_year_atitle'] ); 230 if( isset($params['postcount_year_atitle_one']) ) $Calendar->set( 'postcount_year_atitle_one', $params['postcount_year_atitle_one'] ); 231 // Link type: 232 if( isset($params['link_type']) ) $Calendar->set( 'link_type', $params['link_type'] ); 233 if( isset($params['context_isolation']) ) $Calendar->set( 'context_isolation', $params['context_isolation'] ); 234 235 echo $params['block_start']; 236 237 if( !empty($params['title']) ) 238 { // We want to display a title for the widget block: 239 echo $params['block_title_start']; 240 echo $params['title']; 241 echo $params['block_title_end']; 242 } 243 244 // CONSTRUCT THE WHERE CLAUSE: 245 246 // - - Select a specific Item: 247 // $this->ItemQuery->where_ID( $p, $title ); 248 249 if( $Calendar->link_type == 'context' ) 250 { // We want to preserve the current context: 251 // * - - Restrict to selected blog/categories: 252 $Calendar->ItemQuery->where_chapter2( $Blog, $cat_array, $cat_modifier ); 253 254 // * Restrict to the statuses we want to show: 255 $Calendar->ItemQuery->where_visibility( $show_statuses ); 256 257 // Restrict to selected authors: 258 $Calendar->ItemQuery->where_author( $author ); 259 260 // Restrict to selected assignees: 261 $Calendar->ItemQuery->where_assignees( $assgn ); 262 263 // Restrict to selected satuses: 264 $Calendar->ItemQuery->where_statuses( $status ); 265 266 // - - - + * * if a month is specified in the querystring, load that month: 267 $Calendar->ItemQuery->where_datestart( /* NO m */'', /* NO w */'', $dstart, '', $timestamp_min, $timestamp_max ); 268 269 // Keyword search stuff: 270 $Calendar->ItemQuery->where_keywords( $s, $sentence, $exact ); 271 } 272 else 273 { // We want to preserve only the minimal context: 274 // * - - Restrict to selected blog/categories: 275 $Calendar->ItemQuery->where_chapter2( $Blog, array(), '' ); 276 277 // * Restrict to the statuses we want to show: 278 $Calendar->ItemQuery->where_visibility( $show_statuses ); 279 280 // - - - + * * if a month is specified in the querystring, load that month: 281 $Calendar->ItemQuery->where_datestart( /* NO m */'', /* NO w */'', '', '', $timestamp_min, $timestamp_max ); 282 } 283 284 // DISPLAY: 285 $Calendar->display( ); 286 287 echo $params['block_end']; 288 289 return true; 290 } 291 } 292 293 294 /** 295 * Calendar 296 * 297 * @package evocore 298 */ 299 class Calendar 300 { 301 var $year; 302 303 /** 304 * The month to display or empty in mode 'year' with no selected month. 305 * @var string 306 */ 307 var $month; 308 309 /** 310 * 'month' or 'year' 311 * @var string 312 */ 313 var $mode; 314 315 var $where; 316 /** 317 * SQL query string 318 * @var string 319 */ 320 var $request; 321 /** 322 * Result set 323 */ 324 var $result; 325 /** 326 * Number of rows in result set 327 * @var integer 328 */ 329 var $result_num_rows; 330 331 var $displaycaption; 332 var $monthformat; 333 var $monthstart; 334 var $monthend; 335 var $linktomontharchive; 336 /** 337 * Where to do the navigation 338 * 339 * 'caption' or 'tfoot'; 340 * 341 * @var string 342 */ 343 var $navigation = 'tfoot'; 344 345 var $tablestart; 346 var $tableend; 347 348 var $rowstart; 349 var $rowend; 350 351 var $headerdisplay; 352 var $headerrowstart; 353 var $headerrowend; 354 var $headercellstart; 355 var $headercellend; 356 357 var $cellstart; 358 var $cellend; 359 360 var $emptycellstart; 361 var $emptycellend; 362 363 var $emptycellcontent; 364 365 /** 366 * Do we want to browse years in the caption? True by default for mode == year, 367 * false for mode == month (gets set in constructor). 368 * @var boolean 369 */ 370 var $browseyears; 371 372 /** 373 * Is today in the displayed frame? 374 * @var boolean 375 * @access protected 376 */ 377 var $today_is_visible; 378 379 380 var $link_type; 381 var $context_isolation; 382 383 var $params = array( ); 384 385 /** 386 * Calendar::Calendar(-) 387 * 388 * Constructor 389 * 390 * @param string Month ('YYYYMM'), year ('YYYY'), current ('') 391 * @param array Associative array of parameters. Valid keys are: 392 * - 'min_timestamp' : Minimum unix timestamp the user can browse too or 'query' (Default: 2000-01-01) 393 * - 'max_timestamp' : Maximum unix timestamp the user can browse too or 'query' (Default: now + 1 year ) 394 */ 395 function Calendar( $m = '', $params = array() ) 396 { 397 global $Settings, $localtimenow; 398 399 $this->dbtable = 'T_items__item'; 400 $this->dbprefix = 'post_'; 401 $this->dbIDname = 'post_ID'; 402 403 // OBJECT THAT WILL BE USED TO CONSTRUCT THE WHERE CLAUSE: 404 $this->ItemQuery = new ItemQuery( $this->dbtable, $this->dbprefix, $this->dbIDname ); // COPY!! 405 406 $localyearnow = date( 'Y', $localtimenow ); 407 $localmonthnow = date( 'm', $localtimenow ); 408 409 // Find out which month to display: 410 if( empty($m) ) 411 { // Current month (monthly) 412 $this->year = $localyearnow; 413 $this->month = $localmonthnow; 414 $this->mode = 'month'; 415 416 $this->today_is_visible = true; 417 } 418 else 419 { // We have requested a specific date 420 $this->year = substr($m, 0, 4); 421 if (strlen($m) < 6) 422 { // no month provided 423 $this->mode = 'year'; 424 425 if( $this->year == $localyearnow ) 426 { // we display current year, month gets current 427 $this->month = $localmonthnow; 428 } 429 else 430 { // highlight no month, when not current year 431 $this->month = ''; 432 } 433 } 434 else 435 { 436 $this->month = substr($m, 4, 2); 437 $this->mode = 'month'; 438 } 439 440 $this->today_is_visible = ( $this->year == $localyearnow 441 && ( empty($this->month) || $this->month == $localmonthnow ) ); 442 } 443 444 445 // Default styling: 446 $this->displaycaption = 1; // set this to 0 if you don't want to display the month name 447 $this->monthformat = 'F Y'; 448 $this->linktomontharchive = true; // month displayed as link to month' archive 449 450 $this->tablestart = '<table class="bCalendarTable" cellspacing="0" summary="Monthly calendar with links to each day\'s posts">'."\n"; 451 $this->tableend = '</table>'; 452 453 $this->monthstart = '<caption>'; 454 $this->monthend = "</caption>\n"; 455 456 $this->rowstart = '<tr class="bCalendarRow">' . "\n"; 457 $this->rowend = "</tr>\n"; 458 459 $this->headerdisplay = 'D'; // D => 'Fri'; e => 'F', l (lowercase l) => 'Friday' 460 // These codes are twisted because they're the same as for date formats. 461 // set this to 0 or '' if you don't want to display the "Mon Tue Wed..." header 462 463 $this->headerrowstart = '<thead><tr class="bCalendarRow">' . "\n"; 464 $this->headerrowend = "</tr></thead>\n"; 465 $this->headercellstart = '<th class="bCalendarHeaderCell" abbr="[abbr]" scope="col" title="[abbr]">'; // please leave [abbr] there ! 466 $this->headercellend = "</th>\n"; 467 468 $this->cellstart = '<td class="bCalendarCell">'; 469 $this->cellend = "</td>\n"; 470 471 $this->emptycellstart = '<td class="bCalendarEmptyCell">'; 472 $this->emptycellend = "</td>\n"; 473 $this->emptycellcontent = ' '; 474 475 $this->linkpostcellstart = '<td class="bCalendarLinkPost">'; 476 $this->linkposttodaycellstart = '<td class="bCalendarLinkPostToday">'; 477 $this->todaycellstart = '<td id="bCalendarToday">'; 478 $this->todaycellstartpost = '<td id="bCalendarToday" class="bCalendarLinkPost">'; 479 480 // Where do we want to have the navigation arrows? tfoot or caption 481 $this->navigation = 'tfoot'; 482 483 // Do we want arrows to move one year at a time? 484 $this->browseyears = true; 485 486 /**#@+ 487 * Display number of posts with days/months 488 * 489 * - set to '' (empty) to disable 490 * - %d gets replaced with the number of posts on that day/month 491 */ 492 $this->postcount_month_cell = ''; // in table cell (behind day) 493 $this->postcount_month_cell_one = ''; // -- " -- [for single post] 494 $this->postcount_month_atitle = T_('%d posts'); // in archive links title tag 495 $this->postcount_month_atitle_one = T_('1 post'); // -- " -- [for single post] 496 $this->postcount_year_cell = ''; 497 $this->postcount_year_cell_one = ''; 498 $this->postcount_year_atitle = T_('%d posts'); // in archive links title tag 499 $this->postcount_year_atitle_one = T_('1 post'); // in archive links title tag 500 /**#@-*/ 501 502 // Link type: 503 $this->link_type = 'canonic'; 504 $this->context_isolation = 'm,w,p,title,unit,dstart'; 505 506 // New style params: 507 $this->params = $params; 508 509 // Default values: 510 if( empty( $this->params['min_timestamp'] ) ) 511 { // 2000-01-01: 512 $this->params['min_timestamp'] = mktime( 0, 0, 0, 1, 1, 2000 ); 513 } 514 if( empty( $this->params['max_timestamp'] ) ) 515 { // Now + 1 year: 516 $this->params['max_timestamp'] = mktime( 23, 59, 59, date( 'm', $localtimenow ), date( 'd', $localtimenow ), date( 'Y', $localtimenow )+1 ); 517 } 518 519 } 520 521 522 /* 523 * Calendar->set(-) 524 * 525 * set a variable 526 */ 527 function set( $var, $value ) 528 { 529 $this->$var = $value; 530 } 531 532 533 /** 534 * Display the calendar. 535 * 536 * @todo If a specific day (mode == month) or month (mode == year) is selected, apply another class (default to some border) 537 */ 538 function display() 539 { 540 global $DB; 541 global $weekday, $weekday_abbrev, $weekday_letter, $month, $month_abbrev; 542 global $Settings; 543 544 if( $this->mode == 'month' ) 545 { 546 $end_of_week = ((locale_startofweek() + 7) % 7); 547 548 // fplanque>> note: I am removing the searchframe thing because 1) I don't think it's of any use 549 // and 2) it's brutally inefficient! If someone needs this it should be implemented with A SINGLE 550 // QUERY which gets the last available post (BTW, I think there is already a function for that somwhere) 551 // walter>> As we are just counting items, the ORDER BY db_prefix . date_start doesn't matter. And a side effect 552 // of that is make queries standart compatible (compatible with other databases than MySQL) 553 554 $arc_sql = 'SELECT COUNT(DISTINCT '.$this->dbIDname.') AS item_count, 555 EXTRACT(DAY FROM '.$this->dbprefix.'datestart) AS myday 556 FROM ('.$this->dbtable.' INNER JOIN T_postcats ON '.$this->dbIDname.' = postcat_post_ID) 557 INNER JOIN T_categories ON postcat_cat_ID = cat_ID 558 WHERE EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) = \''.$this->year.'\' 559 AND EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) = \''.$this->month.'\' 560 '.$this->ItemQuery->get_where( ' AND ' ).' 561 GROUP BY myday '.$this->ItemQuery->get_group_by( ', ' ); 562 // echo $this->ItemQuery->where; 563 $arc_result = $DB->get_results( $arc_sql, ARRAY_A ); 564 565 foreach( $arc_result as $arc_row ) 566 { 567 if( !isset( $daysinmonthwithposts[ $arc_row['myday'] ] ) ) 568 { 569 $daysinmonthwithposts[ $arc_row['myday'] ] = 0; 570 } 571 // The '+' situation actually only happens when we have a complex GROUP BY above 572 // (multiple categories wcombined with "ALL") 573 $daysinmonthwithposts[ $arc_row['myday'] ] += $arc_row['item_count']; 574 } 575 576 $daysinmonth = intval(date('t', mktime(0, 0, 0, $this->month, 1, $this->year))); 577 // echo 'days in month=', $daysinmonth; 578 579 580 // caution: offset bug inside (??) 581 $datestartofmonth = mktime(0, 0, 0, $this->month, 1, $this->year ); 582 // echo date( locale_datefmt(), $datestartofmonth ); 583 $calendarblah = get_weekstartend( $datestartofmonth, locale_startofweek() ); 584 $calendarfirst = $calendarblah['start']; 585 586 587 $dateendofmonth = mktime(0, 0, 0, $this->month, $daysinmonth, $this->year); 588 // echo date( locale_datefmt(), $dateendofmonth ); 589 $calendarblah = get_weekstartend( $dateendofmonth, locale_startofweek() ); 590 $calendarlast = $calendarblah['end']; 591 592 593 // here the offset bug is corrected 594 if( (intval(date('d', $calendarfirst)) > 1) && (intval(date('m', $calendarfirst)) == intval($this->month)) ) 595 { 596 #pre_dump( 'with offset bug', date('Y-m-d', $calendarfirst) ); 597 $calendarfirst = $calendarfirst - 604800 /* 1 week */; 598 #pre_dump( 'without offset bug', date('Y-m-d', $calendarfirst) ); 599 } 600 } 601 else 602 { // mode is 'year' 603 // Find months with posts 604 $arc_sql = 'SELECT COUNT(DISTINCT '.$this->dbIDname.') AS item_count, EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) AS mymonth 605 FROM ('.$this->dbtable.' INNER JOIN T_postcats ON '.$this->dbIDname.' = postcat_post_ID) 606 INNER JOIN T_categories ON postcat_cat_ID = cat_ID 607 WHERE EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) = \''.$this->year.'\' ' 608 .$this->ItemQuery->get_where( ' AND ' ).' 609 GROUP BY mymonth '.$this->ItemQuery->get_group_by( ', ' ); 610 $arc_result = $DB->get_results( $arc_sql, ARRAY_A ); 611 612 if( $DB->num_rows > 0 ) 613 { // OK we have a month with posts! 614 foreach( $arc_result as $arc_row ) 615 { 616 $monthswithposts[ $arc_row['mymonth'] ] = $arc_row['item_count']; 617 } 618 } 619 } 620 621 622 // ** display everything ** 623 624 echo $this->tablestart; 625 626 // CAPTION : 627 628 if( $this->displaycaption ) 629 { // caption: 630 echo $this->monthstart; 631 632 if( $this->navigation == 'caption' ) 633 { 634 echo implode( ' ', $this->getNavLinks( 'prev' ) ).' '; 635 } 636 637 if( $this->mode == 'month' ) 638 { // MONTH CAPTION: 639 if( $this->linktomontharchive ) 640 { // chosen month with link to archives 641 echo '<a href="'.$this->archive_link( $this->year, $this->month ).'" title="'.T_('go to month\'s archive').'">'; 642 } 643 644 echo date_i18n($this->monthformat, mktime(0, 0, 0, $this->month, 1, $this->year)); 645 646 if( $this->linktomontharchive ) 647 { // close link to month archive 648 echo '</a>'; 649 } 650 } 651 else 652 { // YEAR CAPTION: 653 echo date_i18n('Y', mktime(0, 0, 0, 1, 1, $this->year)); // display year 654 } 655 656 if( $this->navigation == 'caption' ) 657 { 658 echo ' '.implode( ' ', $this->getNavLinks( 'next' ) ); 659 } 660 661 echo $this->monthend; 662 } 663 664 // HEADER : 665 666 if( !empty($this->headerdisplay) && ($this->mode == 'month') ) 667 { // Weekdays: 668 echo $this->headerrowstart; 669 670 for( $i = locale_startofweek(), $j = $i + 7; $i < $j; $i = $i + 1) 671 { 672 echo str_replace('[abbr]', T_($weekday[($i % 7)]), $this->headercellstart); 673 switch( $this->headerdisplay ) 674 { 675 case 'e': 676 // e => 'F' 677 echo T_($weekday_letter[($i % 7)]); 678 break; 679 680 case 'l': 681 // l (lowercase l) => 'Friday' 682 echo T_($weekday[($i % 7)]); 683 break; 684 685 default: // Backward compatibility: any non emty value will display this 686 // D => 'Fri' 687 echo T_($weekday_abbrev[($i % 7)]); 688 } 689 690 echo $this->headercellend; 691 } 692 693 echo $this->headerrowend; 694 } 695 696 // FOOTER : 697 698 if( $this->navigation == 'tfoot' ) 699 { // We want to display navigation in the table footer: 700 echo "<tfoot>\n"; 701 echo "<tr>\n"; 702 echo '<td colspan="'.( ( $this->mode == 'month' ? 2 : 1 ) + (int)$this->today_is_visible ).'" id="prev">'; 703 echo implode( ' ', $this->getNavLinks( 'prev' ) ); 704 echo "</td>\n"; 705 706 if( $this->today_is_visible ) 707 { 708 if( $this->mode == 'month' ) 709 { 710 echo '<td class="pad"> </td>'."\n"; 711 } 712 } 713 else 714 { 715 echo '<td colspan="'.( $this->mode == 'month' ? '3' : '2' ).'" class="center"><a href="' 716 .$this->archive_link( date('Y'), ( $this->mode == 'month' ? date('m') : NULL ) ) 717 .'">'.T_('Current') 718 .'</a></td>'; 719 } 720 echo '<td colspan="'.( ( $this->mode == 'month' ? 2 : 1 ) + (int)$this->today_is_visible ).'" id="next">'; 721 echo implode( ' ', $this->getNavLinks( 'next' ) ); 722 echo "</td>\n"; 723 echo "</tr>\n"; 724 echo "</tfoot>\n"; 725 } 726 727 // REAL TABLE DATA : 728 729 echo $this->rowstart; 730 731 if( $this->mode == 'year' ) 732 { 733 for ($i = 1; $i < 13; $i = $i + 1) 734 { // For each month: 735 if( isset($monthswithposts[ $i ]) ) 736 { 737 if( $this->month == $i ) 738 { 739 echo $this->todaycellstartpost; 740 } 741 else 742 { 743 echo $this->linkpostcellstart; 744 } 745 echo '<a href="'.$this->archive_link( $this->year, $i ).'"'; 746 if( $monthswithposts[ $i ] > 1 && !empty($this->postcount_year_atitle) ) 747 { // display postcount 748 echo ' title="'.sprintf($this->postcount_year_atitle, $monthswithposts[ $i ]).'"'; 749 } 750 elseif( !empty($this->postcount_year_atitle_one) ) 751 { // display postcount for one post 752 echo ' title="'.sprintf($this->postcount_year_atitle_one, 1).'"'; 753 } 754 echo '>'; 755 } 756 elseif( $this->month == $i ) 757 { // current month 758 echo $this->todaycellstart; 759 } 760 else 761 { 762 echo $this->cellstart; 763 } 764 echo T_($month_abbrev[ zeroise($i, 2) ]); 765 766 if( isset($monthswithposts[ $i ]) ) 767 { // close anchor and show how many posts we have for this month 768 if( $monthswithposts[ $i ] > 1 && !empty($this->postcount_year_cell) ) 769 { // display postcount 770 printf($this->postcount_year_cell, $monthswithposts[ $i ]); 771 } 772 elseif( !empty($this->postcount_year_cell_one) ) 773 { // display postcount for one post 774 printf($this->postcount_year_cell_one, 1); 775 } 776 echo '</a>'; 777 } 778 echo $this->cellend; 779 if( $i == 4 || $i == 8 ) 780 { // new row 781 echo $this->rowend.$this->rowstart; 782 } 783 } 784 } 785 else // mode == 'month' 786 { // Display current month: 787 $dow = 0; 788 $last_day = -1; 789 $dom_displayed = 0; // days of month displayed 790 791 for( $i = $calendarfirst; $i <= $calendarlast; $i = $i + 86400 ) 792 { // loop day by day (86400 seconds = 24 hours; but not on days where daylight saving changes!) 793 if( $dow == 7 ) 794 { // We need to start a new row: 795 if( $dom_displayed >= $daysinmonth ) 796 { // Last day already displayed! 797 break; 798 } 799 echo $this->rowend; 800 echo $this->rowstart; 801 $dow = 0; 802 } 803 $dow++; 804 805 // correct daylight saving ("last day"+86400 would lead to "last day at 23:00") 806 // fp> TODO: use mkdate() 807 while( date('j', $i) == $last_day ) 808 { 809 $i += 3600; 810 } 811 $last_day = date('j', $i); 812 813 814 if (date('m', $i) != $this->month) 815 { // empty cell 816 echo $this->emptycellstart; 817 echo $this->emptycellcontent; 818 echo $this->emptycellend; 819 } 820 else 821 { // This day is in this month 822 $dom_displayed++; 823 $calendartoday = (date('Ymd',$i) == date('Ymd', (time() + $Settings->get('time_difference')))); 824 825 if( isset($daysinmonthwithposts[ date('j', $i) ]) ) 826 { 827 if( $calendartoday ) 828 { 829 echo $this->todaycellstartpost; 830 } 831 else 832 { 833 echo $this->linkpostcellstart; 834 } 835 echo '<a href="'.$this->archive_link( $this->year, $this->month, date('d',$i) ).'"'; 836 if( $daysinmonthwithposts[ date('j', $i) ] > 1 && !empty($this->postcount_month_atitle) ) 837 { // display postcount 838 echo ' title="'.sprintf($this->postcount_month_atitle, $daysinmonthwithposts[ date('j', $i) ]).'"'; 839 } 840 elseif( !empty($this->postcount_month_atitle_one) ) 841 { // display postcount for one post 842 echo ' title="'.sprintf($this->postcount_month_atitle_one, 1).'"'; 843 } 844 echo '>'; 845 } 846 elseif ($calendartoday) 847 { 848 echo $this->todaycellstart; 849 } 850 else 851 { 852 echo $this->cellstart; 853 } 854 echo date('j',$i); 855 if( isset($daysinmonthwithposts[ date('j', $i) ]) ) 856 { 857 if( $daysinmonthwithposts[ date('j', $i) ] > 1 && !empty($this->postcount_month_cell) ) 858 { // display postcount 859 printf($this->postcount_month_cell, $daysinmonthwithposts[ date('j', $i) ]); 860 } 861 elseif( !empty($this->postcount_month_cell_one) ) 862 { // display postcount for one post 863 printf($this->postcount_month_cell_one, 1); 864 } 865 echo '</a>'; 866 } 867 echo $this->cellend; 868 } 869 } // loop day by day 870 } // mode == 'month' 871 872 echo $this->rowend; 873 874 echo $this->tableend; 875 876 } // display(-) 877 878 879 /** 880 * Create a link to archive, using either URL params or extra path info. 881 * 882 * Can make contextual links. 883 * 884 * @param string year 885 * @param string month 886 * @param string day 887 */ 888 function archive_link( $year, $month = NULL, $day = NULL ) 889 { 890 /** 891 * @var Blog 892 */ 893 global $Blog; 894 895 if( $this->link_type == 'context' ) 896 { // We want to preserve context: 897 $url_params = 'm='.$year; 898 if( !empty( $month ) ) 899 { 900 $url_params .= zeroise($month,2); 901 if( !empty( $day ) ) 902 { 903 $url_params .= zeroise($day,2); 904 } 905 } 906 return regenerate_url( $this->context_isolation, $url_params ); 907 } 908 else 909 { // We want a canonic link: 910 return $Blog->gen_archive_url( $year, $month, $day ); 911 } 912 } 913 914 915 /** 916 * Get links to navigate between month / year. 917 * 918 * Unless min/max_timestamp='query' has been specified, this will not do any (time consuming!) queries to check where the posts are. 919 * 920 * @param string 'prev' / 'next' 921 * @return array 922 */ 923 function getNavLinks( $direction ) 924 { 925 global $DB, $localtimenow; 926 927 //pre_dump( 'get_nav_links', $direction ); 928 929 $r = array(); 930 931 if( $this->params['min_timestamp'] == 'query' || $this->params['max_timestamp'] == 'query' ) 932 { // Do inits: 933 // WE NEED SPECIAL QUERY PARAMS WHEN MOVING THOUGH MONTHS ( NO dstart especially! ) 934 $nav_ItemQuery = & new ItemQuery( $this->dbtable, $this->dbprefix, $this->dbIDname ); // TEMP object 935 // Restrict to selected blog/categories: 936 $nav_ItemQuery->where_chapter2( $this->ItemQuery->Blog, $this->ItemQuery->cat_array, $this->ItemQuery->cat_modifier ); 937 // Restrict to the statuses we want to show: 938 $nav_ItemQuery->where_visibility( $this->ItemQuery->show_statuses ); 939 // Restrict to selected authors: 940 $nav_ItemQuery->where_author( $this->ItemQuery->author ); 941 // if a month is specified in the querystring, load that month: 942 $nav_ItemQuery->where_datestart( /* NO m */'', /* NO w */'', /* NO dstart */'', '', $this->ItemQuery->timestamp_min, $this->ItemQuery->timestamp_max ); 943 // Keyword search stuff: 944 $nav_ItemQuery->where_keywords( $this->ItemQuery->keywords, $this->ItemQuery->phrase, $this->ItemQuery->exact ); 945 } 946 947 switch( $direction ) 948 { 949 case 'prev': 950 //pre_dump( $this->params['min_timestamp'] ); 951 $r[] = ''; 952 953 if( empty($this->month) ) 954 { // if $this->month is empty, we're in mode "year" with no selected month 955 $use_range_month = 12; 956 $use_range_day = 31; 957 } 958 else 959 { 960 $use_range_month = $this->month; 961 $use_range_day = 1; // Note: cannot use current day since all months do not have same number of days 962 } 963 964 /* 965 * << (PREV YEAR) 966 */ 967 if( $this->browseyears ) 968 { // We want arrows to move one year at a time 969 if( $this->params['min_timestamp'] == 'query' ) 970 { // Let's query to find the correct year: 971 if( $row = $DB->get_row( 972 'SELECT EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) AS year, 973 EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) AS month 974 FROM ('.$this->dbtable.' INNER JOIN T_postcats ON '.$this->dbIDname.' = postcat_post_ID) 975 INNER JOIN T_categories ON postcat_cat_ID = cat_ID 976 WHERE EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) < '.$this->year.' 977 '.$nav_ItemQuery->get_where( ' AND ' ) 978 .$nav_ItemQuery->get_group_by( ' GROUP BY ' ).' 979 ORDER BY EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) DESC, ABS( '.$use_range_month.' - EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) ) ASC 980 LIMIT 1', OBJECT, 0, 'Calendar: find prev year with posts' ) 981 ) 982 { 983 $prev_year_year = $row->year; 984 $prev_year_month = $row->month; 985 } 986 } 987 else 988 { // Let's see if the previous year is in the desired navigation range: 989 $prev_year_ts = mktime( 0, 0, 0, $use_range_month, $use_range_day, $this->year-1 ); 990 if( $prev_year_ts >= $this->params['min_timestamp'] ) 991 { 992 $prev_year_year = date( 'Y', $prev_year_ts ); 993 $prev_year_month = date( 'm', $prev_year_ts ); 994 } 995 } 996 } 997 998 if( !empty($prev_year_year) ) 999 { // We have a link to display: 1000 $r[] = '<a href="'.$this->archive_link( $prev_year_year, ($this->mode == 'month') ? $prev_year_month : NULL ) 1001 .'" title="'.sprintf( 1002 ( $this->mode == 'month' 1003 ? /* Calendar link title to a month in a previous year */ T_('Previous year (%04d-%02d)') 1004 : /* Calendar link title to a previous year */ T_('Previous year (%04d)') ), 1005 $prev_year_year, $prev_year_month ) 1006 .'"><<</a>'; 1007 } 1008 1009 1010 /* 1011 * < (PREV MONTH) 1012 */ 1013 if( $this->mode == 'month' ) 1014 { // We are browsing months, we'll display arrows to move one month at a time: 1015 if( $this->params['min_timestamp'] == 'query' ) 1016 { // Let's query to find the correct month: 1017 if( $row = $DB->get_row( 1018 'SELECT EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) AS month, 1019 EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) AS year 1020 FROM ('.$this->dbtable.' INNER JOIN T_postcats ON '.$this->dbIDname.' = postcat_post_ID) 1021 INNER JOIN T_categories ON postcat_cat_ID = cat_ID 1022 WHERE 1023 ( 1024 EXTACT(YEAR FROM '.$this->dbprefix.'datestart) < '.($this->year).' 1025 OR ( EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) = '.($this->year).' 1026 AND EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) < '.($this->month).' 1027 ) 1028 ) 1029 '.$nav_ItemQuery->get_where( ' AND ' ) 1030 .$nav_ItemQuery->get_group_by( ' GROUP BY ' ).' 1031 ORDER BY EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) DESC, EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) DESC 1032 LIMIT 1', 1033 OBJECT, 1034 0, 1035 'Calendar: Find prev month with posts' ) 1036 ) 1037 { 1038 $prev_month_year = $row->year; 1039 $prev_month_month = $row->month; 1040 } 1041 } 1042 else 1043 { // Let's see if the previous month is in the desired navigation range: 1044 $prev_month_ts = mktime( 0, 0, 0, $this->month-1, 1, $this->year ); // Note: cannot use current day since all months do not have same number of days 1045 if( $prev_month_ts >= $this->params['min_timestamp'] ) 1046 { 1047 $prev_month_year = date( 'Y', $prev_month_ts ); 1048 $prev_month_month = date( 'm', $prev_month_ts ); 1049 } 1050 } 1051 } 1052 1053 if( !empty($prev_month_year) ) 1054 { // We have a link to display: 1055 $r[] = '<a href="' 1056 .$this->archive_link( $prev_month_year, $prev_month_month ) 1057 .'" title="'.sprintf( T_('Previous month (%04d-%02d)'), $prev_month_year, $prev_month_month ).'"><</a>'; 1058 } 1059 break; 1060 1061 1062 case 'next': 1063 //pre_dump( $this->params['max_timestamp'] ); 1064 1065 /* 1066 * > (NEXT MONTH) 1067 */ 1068 if( $this->mode == 'month' ) 1069 { // We are browsing months, we'll display arrows to move one month at a time: 1070 if( $this->params['max_timestamp'] == 'query' ) 1071 { // Let's query to find the correct month: 1072 if( $row = $DB->get_row( 1073 'SELECT EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) AS month, 1074 EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) AS year 1075 FROM ('.$this->dbtable.' INNER JOIN T_postcats ON '.$this->dbIDname.' = postcat_post_ID) 1076 INNER JOIN T_categories ON postcat_cat_ID = cat_ID 1077 WHERE 1078 ( 1079 EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) > '.($this->year).' 1080 OR ( EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) = '.($this->year).' 1081 AND EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) > '.($this->month).' 1082 ) 1083 ) 1084 '.$nav_ItemQuery->get_where( ' AND ' ) 1085 .$nav_ItemQuery->get_group_by( ' GROUP BY ' ).' 1086 ORDER BY EXTRACT(YEAR FROM '.$this->dbprefix.'datestart), EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) ASC 1087 LIMIT 1', 1088 OBJECT, 1089 0, 1090 'Calendar: Find next month with posts' ) 1091 ) 1092 { 1093 $next_month_year = $row->year; 1094 $next_month_month = $row->month; 1095 } 1096 } 1097 else 1098 { // Let's see if the next month is in the desired navigation range: 1099 $next_month_ts = mktime( 0, 0, 0, $this->month+1, 1, $this->year ); // Note: cannot use current day since all months do not have same number of days 1100 if( $next_month_ts <= $this->params['max_timestamp'] ) 1101 { 1102 $next_month_year = date( 'Y', $next_month_ts ); 1103 $next_month_month = date( 'm', $next_month_ts ); 1104 } 1105 } 1106 } 1107 1108 if( !empty($next_month_year) ) 1109 { // We have a link to display: 1110 $r[] = '<a href="' 1111 .$this->archive_link( $next_month_year, $next_month_month ) 1112 .'" title="'.sprintf( T_('Next month (%04d-%02d)'), $next_month_year, $next_month_month ).'">></a>'; 1113 } 1114 1115 1116 if( empty($this->month) ) 1117 { // if $this->month is empty, we're in mode "year" with no selected month 1118 $use_range_month = 12; 1119 $use_range_day = 31; 1120 } 1121 else 1122 { 1123 $use_range_month = $this->month; 1124 $use_range_day = 1; // Note: cannot use current day since all months do not have same number of days 1125 } 1126 1127 /* 1128 * >> (NEXT YEAR) 1129 */ 1130 if( $this->browseyears ) 1131 { // We want arrows to move one year at a time 1132 if( $this->params['max_timestamp'] == 'query' ) 1133 { // Let's query to find the correct year: 1134 if( $row = $DB->get_row( 1135 'SELECT EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) AS year, 1136 EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) AS month 1137 FROM ('.$this->dbtable.' INNER JOIN T_postcats ON '.$this->dbIDname.' = postcat_post_ID) 1138 INNER JOIN T_categories ON postcat_cat_ID = cat_ID 1139 WHERE EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) > '.$this->year.' 1140 '.$nav_ItemQuery->get_where( ' AND ' ) 1141 .$nav_ItemQuery->get_group_by( ' GROUP BY ' ).' 1142 ORDER BY EXTRACT(YEAR FROM '.$this->dbprefix.'datestart) ASC, ABS( '.$use_range_month.' - EXTRACT(MONTH FROM '.$this->dbprefix.'datestart) ) ASC 1143 LIMIT 1', OBJECT, 0, 'Calendar: find next year with posts' ) 1144 ) 1145 { 1146 $next_year_year = $row->year; 1147 $next_year_month = $row->month; 1148 } 1149 } 1150 else 1151 { // Let's see if the next year is in the desired navigation range: 1152 $next_year_ts = mktime( 0, 0, 0, $use_range_month, $use_range_day, $this->year+1 ); 1153 if( $next_year_ts <= $this->params['max_timestamp'] ) 1154 { 1155 $next_year_year = date( 'Y', $next_year_ts ); 1156 $next_year_month = date( 'm', $next_year_ts ); 1157 } 1158 } 1159 1160 if( !empty($next_year_year) ) 1161 { // We have a link to display: 1162 $r[] = '<a href="'.$this->archive_link( $next_year_year, ($this->mode == 'month') ? $next_year_month : NULL ) 1163 .'" title="'.sprintf( 1164 ( $this->mode == 'month' 1165 ? /* Calendar link title to a month in a following year */ T_('Next year (%04d-%02d)') 1166 : /* Calendar link title to a following year */ T_('Next year (%04d)') ), 1167 $next_year_year, $next_year_month ) 1168 .'">>></a>'; 1169 } 1170 } 1171 break; 1172 } 1173 1174 return $r; 1175 } 1176 1177 } 1178 1179 /* 1180 * $Log: _calendar.plugin.php,v $ 1181 * Revision 1.46 2007/10/09 02:10:50 fplanque 1182 * URL fixes 1183 * 1184 * Revision 1.45 2007/07/01 03:58:08 fplanque 1185 * cat_array cleanup/debug 1186 * 1187 * Revision 1.44 2007/06/23 22:06:47 fplanque 1188 * CSS cleanup 1189 * 1190 * Revision 1.43 2007/06/20 21:42:15 fplanque 1191 * implemented working widget/plugin params 1192 * 1193 * Revision 1.42 2007/05/14 02:43:06 fplanque 1194 * Started renaming tables. There probably won't be a better time than 2.0. 1195 * 1196 * Revision 1.41 2007/04/26 00:11:04 fplanque 1197 * (c) 2007 1198 * 1199 * Revision 1.40 2007/03/29 10:35:40 fplanque 1200 * fix 1201 * 1202 * Revision 1.39 2007/03/25 10:20:02 fplanque 1203 * cleaned up archive urls 1204 * 1205 * Revision 1.38 2007/03/18 16:54:37 waltercruz 1206 * Changing the MySQL date functions to the standart (EXTRACT) ones and killing ORDER BY in monthly and year calendar. 1207 * 1208 * Revision 1.37 2007/02/06 12:49:39 waltercruz 1209 * Changing the date queries to the EXTRACT syntax 1210 * 1211 * Revision 1.36 2007/01/14 01:31:51 fplanque 1212 * do not display title by default (bloated) 1213 * 1214 * Revision 1.35 2007/01/13 18:36:24 fplanque 1215 * renamed "Skin Tag" plugins into "Widget" plugins 1216 * but otherwise they remain basically the same & compatible 1217 * 1218 * Revision 1.34 2006/12/26 03:19:12 fplanque 1219 * assigned a few significant plugin groups 1220 * 1221 * Revision 1.33 2006/12/07 23:13:14 fplanque 1222 * @var needs to have only one argument: the variable type 1223 * Otherwise, I can't code! 1224 * 1225 * Revision 1.32 2006/11/24 18:27:27 blueyed 1226 * Fixed link to b2evo CVS browsing interface in file docblocks 1227 * 1228 * Revision 1.31 2006/11/03 18:22:26 fplanque 1229 * no message 1230 * 1231 * Revision 1.30 2006/10/29 14:52:56 blueyed 1232 * Fixed bug with daylight saving time, which displayed days twice 1233 * 1234 * Revision 1.29 2006/10/14 19:07:17 blueyed 1235 * Removed TODO 1236 * 1237 * Revision 1.28 2006/10/14 19:05:39 blueyed 1238 * Fixed "mktime() expects parameter 4 to be long, string given" warning; doc 1239 */ 1240 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
|