[ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements the ItemList class 2. 4 * 5 * This is the object handling item/post/article lists. 6 * 7 * This file is part of the evoCore framework - {@link http://evocore.net/} 8 * See also {@link http://sourceforge.net/projects/evocms/}. 9 * 10 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/} 11 * 12 * {@internal License choice 13 * - If you have received this file as part of a package, please find the license.txt file in 14 * the same folder or the closest folder above for complete license terms. 15 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 16 * then you must choose one of the following licenses before using the file: 17 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 18 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 19 * }} 20 * 21 * {@internal Open Source relicensing agreement: 22 * }} 23 * 24 * @package evocore 25 * 26 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 27 * @author fplanque: Francois PLANQUE. 28 * 29 * @version $Id: _itemlist.class.php,v 1.4 2007/11/04 17:55:13 fplanque Exp $ 30 */ 31 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 32 33 load_class('/items/model/_itemlistlight.class.php'); 34 35 36 /** 37 * Item List Class 2 38 * 39 * This SECOND implementation will deprecate the first one when finished. 40 * 41 * @package evocore 42 */ 43 class ItemList2 extends ItemListLight 44 { 45 /** 46 * @var array 47 */ 48 var $prevnext_Item = array(); 49 50 /** 51 * Constructor 52 * 53 * @todo add param for saved session filter set 54 * 55 * @param Blog 56 * @param mixed Default filter set: Do not show posts before this timestamp, can be 'now' 57 * @param mixed Default filter set: Do not show posts after this timestamp, can be 'now' 58 * @param integer|NULL Limit 59 * @param string name of cache to be used 60 * @param string prefix to differentiate page/order params when multiple Results appear one same page 61 * @param array restrictions for itemlist (position, contact, firm, ...) key: restriction name, value: ID of the restriction 62 */ 63 function ItemList2( 64 & $Blog, 65 $timestamp_min = NULL, // Do not show posts before this timestamp 66 $timestamp_max = NULL, // Do not show posts after this timestamp 67 $limit = 20, 68 $cache_name = 'ItemCache', // name of cache to be used 69 $param_prefix = '', 70 $filterset_name = '', // Name to be used when saving the filterset (leave empty to use default for collection) 71 $restrict_to = array() // Restrict the item list to a position, or contact, firm..... /* not used yet(?) */ 72 ) 73 { 74 global $Settings; 75 76 // Call parent constructor: 77 parent::ItemListLight( $Blog, $timestamp_min, $timestamp_max, $limit, $cache_name, $param_prefix, $filterset_name, $restrict_to ); 78 } 79 80 81 /** 82 * We want to preview a single post, we are going to fake a lot of things... 83 */ 84 function preview_from_request() 85 { 86 global $current_User; 87 88 if( empty($current_User) ) 89 { // dh> only logged in user's can preview. Alternatively we need those checks where $current_User gets used below. 90 return; 91 } 92 93 global $DB, $localtimenow, $Messages, $BlogCache; 94 global $Plugins; 95 96 $preview_userid = param( 'preview_userid', 'integer', true ); 97 $post_status = param( 'post_status', 'string', true ); 98 $post_locale = param( 'post_locale', 'string', $current_User->locale ); 99 $content = param( 'content', 'html', true ); 100 $post_title = param( 'post_title', 'html', true ); 101 $post_excerpt = param( 'post_excerpt', 'string', true ); 102 $post_url = param( 'post_url', 'string', '' ); 103 $post_category = param( 'post_category', 'integer', true ); 104 $post_views = param( 'post_views', 'integer', 0 ); 105 $renderers = param( 'renderers', 'array', array('default') ); 106 if( ! is_array($renderers) ) 107 { // dh> workaround for param() bug. See rev 1.93 of /inc/_misc/_misc.funcs.php 108 $renderers = array('default'); 109 } 110 $comment_Blog = & $BlogCache->get_by_ID( get_catblog( $post_category ) ); 111 if( $comment_Blog->allowcomments == 'post_by_post' ) 112 { // param is required 113 $post_comment_status = param( 'post_comment_status', 'string', true ); 114 } 115 else 116 { 117 $post_comment_status = $comment_Blog->allowcomments; 118 } 119 120 121 // Get issue date, using the user's locale (because it's entered like this in the form): 122 locale_temp_switch( $current_User->locale ); 123 124 param_date( 'item_issue_date', T_('Please enter a valid issue date.'), false ); 125 // TODO: dh> get_param() is always true here, also on invalid dates: 126 if( strlen(get_param('item_issue_date')) ) 127 { // only set it, if a date was given: 128 param_time( 'item_issue_time' ); 129 $item_issue_date = form_date( get_param( 'item_issue_date' ), get_param( 'item_issue_time' ) ); // TODO: cleanup... 130 } 131 else 132 { 133 $item_issue_date = date( 'Y-m-d H:i:s', $localtimenow ); 134 } 135 locale_restore_previous(); 136 137 138 if( !($item_typ_ID = param( 'item_typ_ID', 'integer', NULL )) ) 139 $item_typ_ID = NULL; 140 if( !($item_st_ID = param( 'item_st_ID', 'integer', NULL )) ) 141 $item_st_ID = NULL; 142 if( !($item_assigned_user_ID = param( 'item_assigned_user_ID', 'integer', NULL )) ) 143 $item_assigned_user_ID = NULL; 144 if( !($item_deadline = param( 'item_deadline', 'string', NULL )) ) 145 $item_deadline = NULL; 146 $item_priority = param( 'item_priority', 'integer', NULL ); // QUESTION: can this be also empty/NULL? 147 148 // Do some optional filtering on the content 149 // Typically stuff that will help the content to validate 150 // Useful for code display. 151 // Will probably be used for validation also. 152 $Plugins_admin = & get_Cache('Plugins_admin'); 153 $Plugins_admin->filter_contents( $post_title /* by ref */, $content /* by ref */, $renderers ); 154 155 $post_title = format_to_post( $post_title ); 156 $content = format_to_post( $content ); 157 158 $this->sql = "SELECT 159 0 AS post_ID, 160 $preview_userid AS post_creator_user_ID, 161 $preview_userid AS post_lastedit_user_ID, 162 '$item_issue_date' AS post_datestart, 163 '$item_issue_date' AS post_datecreated, 164 '$item_issue_date' AS post_datemodified, 165 '".$DB->escape($post_status)."' AS post_status, 166 '".$DB->escape($post_locale)."' AS post_locale, 167 '".$DB->escape($content)."' AS post_content, 168 '".$DB->escape($post_title)."' AS post_title, 169 '".$DB->escape($post_excerpt)."' AS post_excerpt, 170 NULL AS post_urltitle, 171 '".$DB->escape($post_url)."' AS post_url, 172 $post_category AS post_main_cat_ID, 173 $post_views AS post_views, 174 '' AS post_flags, 175 'noreq' AS post_notifications_status, 176 NULL AS post_notifications_ctsk_ID, 177 ".bpost_count_words( $content )." AS post_wordcount, 178 ".$DB->quote($post_comment_status)." AS post_comment_status, 179 '".$DB->escape( implode( '.', $renderers ) )."' AS post_renderers, 180 ".$DB->quote($item_assigned_user_ID)." AS post_assigned_user_ID, 181 ".$DB->quote($item_typ_ID)." AS post_ptyp_ID, 182 ".$DB->quote($item_st_ID)." AS post_pst_ID, 183 ".$DB->quote($item_deadline)." AS post_datedeadline, 184 ".$DB->quote($item_priority)." AS post_priority"; 185 186 $this->total_rows = 1; 187 $this->total_pages = 1; 188 $this->page = 1; 189 190 // ATTENTION: we skip the parent on purpose here!! fp> refactor 191 DataObjectList2::query( false, false, false, 'PREVIEW QUERY' ); 192 193 $Item = & $this->Cache->instantiate( $this->rows[0] ); 194 195 // Trigger plugin event, allowing to manipulate or validate the item before it gets previewed 196 $Plugins->trigger_event( 'AppendItemPreviewTransact', array( 'Item' => & $Item ) ); 197 198 if( $errcontent = $Messages->display( T_('Invalid post, please correct these errors:'), '', false, 'error' ) ) 199 { 200 $Item->content = $errcontent."\n<hr />\n".$content; 201 } 202 203 // little funky fix for IEwin, rawk on that code 204 global $Hit; 205 if( ($Hit->is_winIE) && (!isset($IEWin_bookmarklet_fix)) ) 206 { // QUESTION: Is this still needed? What about $IEWin_bookmarklet_fix? (blueyed) 207 $Item->content = preg_replace('/\%u([0-9A-F]{4,4})/e', "'&#'.base_convert('\\1',16,10). ';'", $Item->content); 208 } 209 } 210 211 212 /** 213 * Run Query: GET DATA ROWS *** HEAVY *** 214 */ 215 function query() 216 { 217 global $DB; 218 219 if( !is_null( $this->rows ) ) 220 { // Query has already executed: 221 return; 222 } 223 224 // INNIT THE QUERY: 225 $this->query_init(); 226 227 // Results style orders: 228 // $this->ItemQuery->ORDER_BY_prepend( $this->get_order_field_list() ); 229 230 231 // We are going to proceed in two steps (we simulate a subquery) 232 // 1) we get the IDs we need 233 // 2) we get all the other fields matching these IDs 234 // This is more efficient than manipulating all fields at once. 235 236 // *** STEP 1 *** 237 // walter> Accordding to the standart, to DISTINCT queries, all columns used 238 // in ORDER BY must appear in the query. This make que query work with PostgreSQL and 239 // other databases. 240 // fp> That can dramatically fatten the returned data. You must handle this in the postgres class (check that order fields are in select) 241 $step1_sql = 'SELECT DISTINCT '.$this->Cache->dbIDname // .', '.implode( ', ', $order_cols_to_select ) 242 .$this->ItemQuery->get_from() 243 .$this->ItemQuery->get_where() 244 .$this->ItemQuery->get_group_by() 245 .$this->ItemQuery->get_order_by() 246 .$this->ItemQuery->get_limit(); 247 248 // echo $DB->format_query( $step1_sql ); 249 250 // Get list of the IDs we need: 251 $ID_list = implode( ',', $DB->get_col( $step1_sql, 0, 'ItemList2::Query() Step 1: Get ID list' ) ); 252 253 // *** STEP 2 *** 254 $this->sql = 'SELECT * 255 FROM '.$this->Cache->dbtablename; 256 if( !empty($ID_list) ) 257 { 258 $this->sql .= ' WHERE '.$this->Cache->dbIDname.' IN ('.$ID_list.') ' 259 .$this->ItemQuery->get_order_by(); 260 } 261 else 262 { 263 $this->sql .= ' WHERE 0'; 264 } 265 266 //echo $DB->format_query( $this->sql ); 267 268 // ATTENTION: we skip the parent on purpose here!! fp> refactor 269 DataObjectList2::query( false, false, false, 'ItemList2::Query() Step 2' ); 270 } 271 272 273 /** 274 * If the list is sorted by category... 275 * 276 * This is basically just a stub for backward compatibility 277 */ 278 function & get_item() 279 { 280 if( $this->group_by_cat == 1 ) 281 { // This is the first call to get_item() after get_category_group() 282 $this->group_by_cat = 2; 283 // Return the object we already got in get_category_group(): 284 return $this->current_Obj; 285 } 286 287 $Item = & parent::get_next(); 288 289 if( !empty($Item) && $this->group_by_cat == 2 && $Item->main_cat_ID != $this->main_cat_ID ) 290 { // We have just hit a new category! 291 $this->group_by_cat == 0; // For info only. 292 $r = false; 293 return $r; 294 } 295 296 //pre_dump( $Item ); 297 298 return $Item; 299 } 300 301 302 /** 303 * Returns values needed to make sort links for a given column 304 * 305 * Returns an array containing the following values: 306 * - current_order : 'ASC', 'DESC' or '' 307 * - order_asc : url needed to order in ascending order 308 * - order_desc 309 * - order_toggle : url needed to toggle sort order 310 * 311 * @param integer column to sort 312 * @return array 313 */ 314 function get_col_sort_values( $col_idx ) 315 { 316 $col_order_fields = $this->cols[$col_idx]['order']; 317 318 // pre_dump( $col_order_fields, $this->filters['orderby'], $this->filters['order'] ); 319 320 // Current order: 321 if( $this->filters['orderby'] == $col_order_fields ) 322 { 323 $col_sort_values['current_order'] = $this->filters['order']; 324 } 325 else 326 { 327 $col_sort_values['current_order'] = ''; 328 } 329 330 331 // Generate sort values to use for sorting on the current column: 332 $col_sort_values['order_asc'] = regenerate_url( array($this->param_prefix.'order',$this->param_prefix.'orderby'), 333 $this->param_prefix.'order=ASC&'.$this->param_prefix.'orderby='.$col_order_fields ); 334 $col_sort_values['order_desc'] = regenerate_url( array($this->param_prefix.'order',$this->param_prefix.'orderby'), 335 $this->param_prefix.'order=DESC&'.$this->param_prefix.'orderby='.$col_order_fields ); 336 337 if( !$col_sort_values['current_order'] && isset( $this->cols[$col_idx]['default_dir'] ) ) 338 { // There is no current order on this column and a default order direction is set for it 339 // So set a default order direction for it 340 341 if( $this->cols[$col_idx]['default_dir'] == 'A' ) 342 { // The default order direction is A, so set its toogle order to the order_asc 343 $col_sort_values['order_toggle'] = $col_sort_values['order_asc']; 344 } 345 else 346 { // The default order direction is A, so set its toogle order to the order_desc 347 $col_sort_values['order_toggle'] = $col_sort_values['order_desc']; 348 } 349 } 350 elseif( $col_sort_values['current_order'] == 'ASC' ) 351 { // There is an ASC current order on this column, so set its toogle order to the order_desc 352 $col_sort_values['order_toggle'] = $col_sort_values['order_desc']; 353 } 354 else 355 { // There is a DESC or NO current order on this column, so set its toogle order to the order_asc 356 $col_sort_values['order_toggle'] = $col_sort_values['order_asc']; 357 } 358 359 // pre_dump( $col_sort_values ); 360 361 return $col_sort_values; 362 } 363 364 365 366 /** 367 * Link to previous and next link in collection 368 */ 369 function prevnext_item_links( $params ) 370 { 371 $params = array_merge( array( 372 'template' => '$prev$$next$', 373 'prev_text' => '« $title$', 374 'prev_no_item' => '', 375 'next_text' => '$title$ »', 376 'next_no_item' => '', 377 ), $params ); 378 379 $prev = $this->prev_item_link( $params['prev_start'], $params['prev_end'], $params[ 'prev_text' ], $params[ 'prev_no_item' ], false ); 380 $next = $this->next_item_link( $params['next_start'], $params['next_end'], $params[ 'next_text' ], $params[ 'next_no_item' ], false ); 381 382 $output = str_replace( '$prev$', $prev, $params['template'] ); 383 $output = str_replace( '$next$', $next, $output ); 384 385 if( !empty( $output ) ) 386 { // we have some output, lets wrap it 387 echo( $params['block_start'] ); 388 echo $output; 389 echo( $params['block_end'] ); 390 } 391 } 392 393 394 /** 395 * Skip to previous 396 */ 397 function prev_item_link( $before = '', $after = '', $text = '« $title$', $no_item = '', $display = true ) 398 { 399 /** 400 * @var Item 401 */ 402 $prev_Item = & $this->get_prevnext_Item( 'prev' ); 403 404 if( !is_null($prev_Item) ) 405 { 406 $output = $before; 407 $output .= $prev_Item->get_permanent_link( $text ); 408 $output .= $after; 409 } 410 else 411 { 412 $output = $no_item; 413 } 414 if( $display ) echo $output; 415 return $output; 416 } 417 418 419 /** 420 * Skip to next 421 */ 422 function next_item_link( $before = '', $after = '', $text = '$title$ »', $no_item = '', $display = true ) 423 { 424 /** 425 * @var Item 426 */ 427 $next_Item = & $this->get_prevnext_Item( 'next' ); 428 429 if( !is_null($next_Item) ) 430 { 431 $output = $before; 432 $output .= $next_Item->get_permanent_link( $text ); 433 $output .= $after; 434 } 435 else 436 { 437 $output = $no_item; 438 } 439 if( $display ) echo $output; 440 return $output; 441 } 442 443 444 /** 445 * Skip to previous/next Item 446 * 447 * If several items share the same spot (like same issue datetime) then they'll get all skipped at once. 448 * 449 * @param string prev | next (relative to the current sort order) 450 */ 451 function & get_prevnext_Item( $direction = 'next' ) 452 { 453 global $DB, $ItemCache; 454 455 if( ! $this->single_post ) 456 { // We are not on a single post: 457 $r = NULL; 458 return $r; 459 } 460 461 /** 462 * @var Item 463 */ 464 $current_Item = $this->get_by_idx(0); 465 466 if( is_null($current_Item) ) 467 { 468 debug_die( 'no current item!!!' ); 469 } 470 471 if( $current_Item->ptyp_ID == 1000 ) // page 472 { // We are not on a REGULAR post: 473 $r = NULL; 474 return $r; 475 } 476 477 if( !empty( $this->prevnext_Item[$direction] ) ) 478 { 479 return $this->prevnext_Item[$direction]; 480 } 481 482 $next_Query = & new ItemQuery( $this->Cache->dbtablename, $this->Cache->dbprefix, $this->Cache->dbIDname ); 483 484 // GENERATE THE QUERY: 485 486 /* 487 * filtering stuff: 488 */ 489 $next_Query->where_chapter2( $this->Blog, $this->filters['cat_array'], $this->filters['cat_modifier'], 490 $this->filters['cat_focus'] ); 491 $next_Query->where_author( $this->filters['authors'] ); 492 $next_Query->where_assignees( $this->filters['assignees'] ); 493 $next_Query->where_author_assignee( $this->filters['author_assignee'] ); 494 $next_Query->where_locale( $this->filters['lc'] ); 495 $next_Query->where_statuses( $this->filters['statuses'] ); 496 $next_Query->where_types( $this->filters['types'] ); 497 $next_Query->where_keywords( $this->filters['keywords'], $this->filters['phrase'], $this->filters['exact'] ); 498 // $next_Query->where_ID( $this->filters['post_ID'], $this->filters['post_title'] ); 499 $next_Query->where_datestart( $this->filters['ymdhms'], $this->filters['week'], 500 $this->filters['ymdhms_min'], $this->filters['ymdhms_max'], 501 $this->filters['ts_min'], $this->filters['ts_max'] ); 502 $next_Query->where_visibility( $this->filters['visibility_array'] ); 503 504 /* 505 * ORDER BY stuff: 506 */ 507 if( ($direction == 'next' && $this->filters['order'] == 'DESC') 508 || ($direction == 'prev' && $this->filters['order'] == 'ASC') ) 509 { 510 $order = 'DESC'; 511 $operator = ' < '; 512 } 513 else 514 { 515 $order = 'ASC'; 516 $operator = ' > '; 517 } 518 519 $orderby = str_replace( ' ', ',', $this->filters['orderby'] ); 520 $orderby_array = explode( ',', $orderby ); 521 522 // Format each order param with default column names: 523 $orderbyorder_array = preg_replace( '#^(.+)$#', $this->Cache->dbprefix.'$1 '.$order, $orderby_array ); 524 525 // Add an ID parameter to make sure there is no ambiguity in ordering on similar items: 526 $orderbyorder_array[] = $this->Cache->dbIDname.' '.$order; 527 528 $order_by = implode( ', ', $orderbyorder_array ); 529 530 531 $next_Query->order_by( $order_by ); 532 533 534 // LIMIT to 1 single result 535 $next_Query->LIMIT( '1' ); 536 537 // fp> TODO: I think some additional limits need to come back here (for timespans) 538 539 540 /* 541 * Position right after the current element depending on current sorting params 542 * 543 * fp> WARNING: This only works with the FIRST order param! 544 * If there are several items on the same issuedatetime for example, they'll all get skipped at once! 545 * You cannot put several criterias combined with AND!!! (you would need stuf like a>a0 OR (a=a0 AND b>b0) etc. 546 * This is too complex, so I'm going to call this function a "skip to next" that cannot digg into details 547 */ 548 switch( $orderby_array[0] ) 549 { 550 case 'datestart': 551 // special var name: 552 $next_Query->WHERE_and( $this->Cache->dbprefix.$orderby_array[0] 553 .$operator 554 .$DB->quote($current_Item->issue_date) ); 555 break; 556 557 case 'title': 558 case 'datecreated': 559 case 'datemodified': 560 case 'urltitle': 561 case 'priority': // Note: will skip to next priority level 562 $next_Query->WHERE_and( $this->Cache->dbprefix.$orderby_array[0] 563 .$operator 564 .$DB->quote($current_Item->{$orderby_array[0]}) ); 565 break; 566 567 default: 568 echo 'WARNING: unhandled sorting: '.htmlspecialchars( $orderby_array[0] ); 569 } 570 571 572 573 // GET DATA ROWS: 574 575 576 // We are going to proceed in two steps (we simulate a subquery) 577 // 1) we get the IDs we need 578 // 2) we get all the other fields matching these IDs 579 // This is more efficient than manipulating all fields at once. 580 581 // Step 1: 582 $step1_sql = 'SELECT DISTINCT '.$this->Cache->dbIDname 583 .$next_Query->get_from() 584 .$next_Query->get_where() 585 .$next_Query->get_group_by() 586 .$next_Query->get_order_by() 587 .$next_Query->get_limit(); 588 589 // echo $DB->format_query( $step1_sql ); 590 591 // Get list of the IDs we need: 592 $next_ID = $DB->get_var( $step1_sql, 0, 0, 'Get ID of next item' ); 593 594 // Step 2: get the item (may be NULL): 595 $this->prevnext_Item[$direction] = & $ItemCache->get_by_ID( $next_ID, true, false ); 596 597 return $this->prevnext_Item[$direction]; 598 599 } 600 } 601 602 /* 603 * $Log: _itemlist.class.php,v $ 604 * Revision 1.4 2007/11/04 17:55:13 fplanque 605 * More cleanup 606 * 607 * Revision 1.3 2007/09/09 12:51:58 fplanque 608 * cleanup 609 * 610 * Revision 1.2 2007/09/09 09:15:59 yabs 611 * validation 612 * 613 * Revision 1.1 2007/06/25 11:00:26 fplanque 614 * MODULES (refactored MVC) 615 * 616 * Revision 1.65 2007/05/28 15:18:30 fplanque 617 * cleanup 618 * 619 * Revision 1.64 2007/05/13 22:02:07 fplanque 620 * removed bloated $object_def 621 * 622 * Revision 1.63 2007/04/26 00:11:12 fplanque 623 * (c) 2007 624 * 625 * Revision 1.62 2007/04/05 22:57:33 fplanque 626 * Added hook: UnfilterItemContents 627 * 628 * Revision 1.61 2007/03/31 22:46:47 fplanque 629 * FilterItemContent event 630 * 631 * Revision 1.60 2007/03/26 18:51:58 fplanque 632 * fix 633 * 634 * Revision 1.59 2007/03/26 14:21:30 fplanque 635 * better defaults for pages implementation 636 * 637 * Revision 1.58 2007/03/26 12:59:18 fplanque 638 * basic pages support 639 * 640 * Revision 1.57 2007/03/19 23:59:18 fplanque 641 * fixed preview 642 * 643 * Revision 1.56 2007/03/19 21:57:36 fplanque 644 * ItemLists: $cat_focus and $unit extensions 645 * 646 * Revision 1.55 2007/03/18 03:43:19 fplanque 647 * EXPERIMENTAL 648 * Splitting Item/ItemLight and ItemList/ItemListLight 649 * Goal: Handle Items with less footprint than with their full content 650 * (will be even worse with multiple languages/revisions per Item) 651 * 652 * Revision 1.53 2007/03/18 01:39:54 fplanque 653 * renamed _main.php to main.page.php to comply with 2.0 naming scheme. 654 * (more to come) 655 * 656 * Revision 1.52 2007/03/12 14:02:41 waltercruz 657 * Adding the columns in order by to the query to satisfy the SQL Standarts 658 * 659 * Revision 1.51 2007/03/03 03:37:56 fplanque 660 * extended prev/next item links 661 * 662 * Revision 1.50 2007/03/03 01:14:12 fplanque 663 * new methods for navigating through posts in single item display mode 664 * 665 * Revision 1.49 2007/01/26 04:49:17 fplanque 666 * cleanup 667 * 668 * Revision 1.48 2007/01/23 09:25:40 fplanque 669 * Configurable sort order. 670 * 671 * Revision 1.47 2007/01/20 23:05:11 blueyed 672 * todos 673 * 674 * Revision 1.46 2007/01/19 21:48:09 blueyed 675 * Fixed possible notice in preview_from_request() 676 * 677 * Revision 1.45 2006/12/17 23:42:38 fplanque 678 * Removed special behavior of blog #1. Any blog can now aggregate any other combination of blogs. 679 * Look into Advanced Settings for the aggregating blog. 680 * There may be side effects and new bugs created by this. Please report them :] 681 * 682 * Revision 1.44 2006/12/05 00:01:15 fplanque 683 * enhanced photoblog skin 684 * 685 * Revision 1.43 2006/12/04 18:16:50 fplanque 686 * Each blog can now have its own "number of page/days to display" settings 687 * 688 * Revision 1.42 2006/11/28 00:33:01 blueyed 689 * Removed DB::compString() (never used) and DB::get_list() (just a macro and better to have in the 4 used places directly; Cleanup/normalization; no extended regexp, when not needed! 690 * 691 * Revision 1.41 2006/11/24 18:27:24 blueyed 692 * Fixed link to b2evo CVS browsing interface in file docblocks 693 * 694 * Revision 1.40 2006/11/17 00:19:22 blueyed 695 * Switch to user locale for validating item_issue_date, because it uses T_() 696 * 697 * Revision 1.39 2006/11/17 00:09:15 blueyed 698 * TODO: error/E_NOTICE with invalid issue date 699 * 700 * Revision 1.38 2006/11/12 02:13:19 blueyed 701 * doc, whitespace 702 * 703 * Revision 1.37 2006/11/11 17:33:50 blueyed 704 * doc 705 * 706 * Revision 1.36 2006/11/04 19:38:53 blueyed 707 * Fixes for hook move 708 * 709 * Revision 1.35 2006/11/02 16:00:42 blueyed 710 * Moved AppendItemPreviewTransact hook, so it can throw error messages 711 * 712 * Revision 1.34 2006/10/31 00:33:26 blueyed 713 * Fixed item_issue_date for preview 714 * 715 * Revision 1.33 2006/10/10 17:09:39 blueyed 716 * doc 717 * 718 * Revision 1.32 2006/10/08 22:35:01 blueyed 719 * TODO: limit===NULL handling 720 * 721 * Revision 1.31 2006/10/05 01:17:36 blueyed 722 * Removed unnecessary/doubled call to Item::update_renderers_from_Plugins() 723 * 724 * Revision 1.30 2006/10/05 01:06:36 blueyed 725 * Removed dirty "hack"; added ItemApplyAsRenderer hook instead. 726 */ 727 ?>
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 |
![]() |