b2evolution PHP Cross Reference Blogging Systems

Source: /inc/_blog_main.inc.php - 718 lines - 27268 bytes - Text - Print

Description: This file loads and initializes the blog to be displayed. This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}. See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file loads and initializes the blog to be displayed.
   4   *
   5   * This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}.
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}.
   9   * Parts of this file are copyright (c)2004-2005 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10   *
  11   * @license http://b2evolution.net/about/license.html GNU General Public License (GPL)
  12   *
  13   * {@internal Open Source relicensing agreement:
  14   * Daniel HAHLER grants Francois PLANQUE the right to license
  15   * Daniel HAHLER's contributions to this file and the b2evolution project
  16   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  17   * }}
  18   *
  19   * @package main
  20   *
  21   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  22   * @author blueyed: Daniel HAHLER
  23   * @author fplanque: Francois PLANQUE
  24   *
  25   * @version $Id: _blog_main.inc.php 6136 2014-03-08 07:59:48Z manuel $
  26   */
  27  if( !defined('EVO_CONFIG_LOADED') ) die( 'Please, do not access this page directly.' );
  28  
  29  /**
  30   * Initialize everything:
  31   */
  32  require_once dirname(__FILE__).'/_main.inc.php';
  33  
  34  load_funcs('skins/_skin.funcs.php');
  35  load_class( 'items/model/_itemlist.class.php', 'ItemList' );
  36  
  37  // fp> A lot of time (like 40ms) will be consumed the first time a new Blog object is created.
  38  // This happens within _BLOG_MAIN bloc in non logged in mode and is pretty much perturbing.
  39  // Trying to create a dummy Blog below move the delay out.
  40  // The constructor doesn't consume any time at all.
  41  // This is very strange. Is it because of recursive class loading that happens when instanciating a Blog?
  42  //$dummy = new Blog();
  43  $Timer->start( '_BLOG_MAIN.inc' );
  44  
  45  
  46  /*
  47   * blog ID. This is a little bit special.
  48   *
  49   * In most cases $blog should be set by a stub file and the param() call below will just check that it's an integer.
  50   *
  51   * Note we do NOT memorize the param as we don't want it in regenerate_url() calls.
  52   * Whenever we do, index.php will already have called param() with memorize=true
  53   *
  54   * In some cases $blog will not have been set before and it will be set with the param() call below.
  55   * Currently, this only happens with the old /xmlsrv/ RSS stubs.
  56   */
  57  param( 'blog', 'integer', '', false );
  58  
  59  // Getting current blog info:
  60  $BlogCache = & get_BlogCache();
  61  /**
  62   * @var Blog
  63   */
  64  $Blog = & $BlogCache->get_by_ID( $blog, false, false );
  65  if( empty( $Blog ) )
  66  {
  67      require $skins_path.'_404_blog_not_found.main.php'; // error & exit
  68      // EXIT.
  69  }
  70  
  71  
  72  // Init $disp
  73  param( 'disp', '/^[a-z0-9\-_]+$/', 'posts', true );
  74  $disp_detail = '';
  75  
  76  
  77  /*
  78   * _______________________________ Locale / Charset for the Blog _________________________________
  79   *
  80      TODO: blueyed>> This should get moved as default to the locale detection in _main.inc.php,
  81              as we only want to activate the I/O charset, which is probably the user's..
  82              It prevents using a locale/charset in the front office, apart from the one given as default for the blog!!
  83  fp>there is no blog defined in _main and there should not be any
  84  blueyed> Sure, but that means we should either split it, or use the locale here only, if there's no-one given with higher priority.
  85  */
  86  // Activate matching locale:
  87  $Debuglog->add( 'Activating blog locale: '.$Blog->get('locale'), 'locale' );
  88  locale_activate( $Blog->get('locale') );
  89  
  90  
  91  // Re-Init charset handling, in case current_charset has changed:
  92  if( init_charsets( $current_charset ) )
  93  {
  94    // Reload Blog(s) (for encoding of name, tagline etc):
  95    $BlogCache->clear();
  96  
  97    $Blog = & $BlogCache->get_by_ID( $blog );
  98    if( is_logged_in() )
  99    { // We also need to reload the current User with the new final charset
 100        $UserCache = & get_UserCache();
 101      $UserCache->clear();
 102      $current_User = & $UserCache->get_by_ID( $current_User->ID );
 103    }
 104  }
 105  
 106  
 107  /*
 108   * _____________________________ Extra path info decoding ________________________________
 109   *
 110   * This will translate extra path into 'regular' params.
 111   *
 112   * Decoding should try to work like this:
 113   *
 114   * baseurl/blog-urlname/junk/.../junk/post-title    -> points to a single post (no ending slash)
 115   * baseurl/blog-urlname/junk/.../junk/p142          -> points to a single post
 116   * baseurl/blog-urlname/2006/                       -> points to a yearly archive because of ending slash + 4 digits
 117   * baseurl/blog-urlname/2006/12/                    -> points to a monthly archive
 118   * baseurl/blog-urlname/2006/12/31/                 -> points to a daily archive
 119   * baseurl/blog-urlname/2006/w53/                   -> points to a weekly archive
 120   * baseurl/blog-urlname/junk/.../junk/chap-urlname/ -> points to a single chapter/category (because of ending slash)
 121   * Note: category names cannot be named like this [a-z][0-9]+
 122   */
 123  if( ! isset( $resolve_extra_path ) ) { $resolve_extra_path = true; }
 124  if( $resolve_extra_path )
 125  {
 126      // Check and Remove blog base URI from ReqPath:
 127      $blog_baseuri = substr( $Blog->gen_baseurl(), strlen( $Blog->get_baseurl_root() ) );
 128      $Debuglog->add( 'blog_baseuri: "'.$blog_baseuri.'"', 'params' );
 129  
 130      // Remove trailer:
 131      $blog_baseuri_regexp = preg_replace( '~(\.php[0-9]?)?/?$~', '', $blog_baseuri );
 132      // Read possibilities in order to get a broad match:
 133      $blog_baseuri_regexp = '~^'.preg_quote( $blog_baseuri_regexp, '~' ).'(\.php[0-9]?)?/(.+)$~';
 134      // pre_dump( '', 'blog_baseuri_regexp: "', $blog_baseuri_regexp );
 135  
 136      if( preg_match( $blog_baseuri_regexp, $ReqPath, $matches ) )
 137      { // We have extra path info
 138          $path_string = $matches[2];
 139  
 140          $Debuglog->add( 'Extra path info found! path_string=' . $path_string , 'params' );
 141          // echo "path=[$path_string]<br />";
 142  
 143          // Replace encoded ";" and ":" with regular chars (used for tags)
 144          // TODO: dh> why not urldecode it altogether? fp> would prolly make sense but requires testing -- note: check with tags (move urldecode from tags up here)
 145          // TODO: PHP5: use str_ireplace
 146          $path_string = str_replace(
 147              array('%3b', '%3B', '%3a', '%3A'),
 148              array(';', ';', ':', ':'),
 149              $path_string );
 150  
 151          // Slice the path:
 152          $path_elements = preg_split( '~/~', $path_string, 20, PREG_SPLIT_NO_EMPTY );
 153          // pre_dump( '', $path_elements, $pagenow );
 154  
 155          // PREVENT index.php or blog1.php etc from being considered as a slug later on.
 156          if( isset( $path_elements[0] ) && $path_elements[0] == $pagenow )
 157          { // Ignore element that is the current PHP file name (ideally this URL will later be redirected to a canonical URL without any .php file in the URL)
 158              array_shift( $path_elements );
 159              $Debuglog->add( 'Ignoring *.php in extra path info' , 'params' );
 160          }
 161  
 162          if( isset( $path_elements[0] )
 163                  && ( $path_elements[0] == $Blog->stub
 164                          || $path_elements[0] == $Blog->urlname ) )
 165          { // Ignore stub file (if it ends with .php it should already have been filtered out above)
 166              array_shift( $path_elements );
 167              $Debuglog->add( 'Ignoring stub filename OR blog urlname in extra path info' , 'params' );
 168          }
 169          // pre_dump( $path_elements );
 170  
 171          // Do we still have extra path info to decode?
 172          if( count($path_elements) )
 173          {
 174              // TODO: dh> add plugin hook here, which would allow to handle path elements (name spaces in clean URLs), and to override internal functionality (e.g. handle tags in a different way).
 175              // Is this a tag ("prefix-only" mode)?
 176              if( $Blog->get_setting('tag_links') == 'prefix-only'
 177                  && count($path_elements) == 2
 178                  && $path_elements[0] == $Blog->get_setting('tag_prefix')
 179                  && isset($path_elements[1]) )
 180              {
 181                  $tag = strip_tags(urldecode($path_elements[1]));
 182  
 183                  // # of posts per page for tag page:
 184                  if( ! $posts = $Blog->get_setting( 'tag_posts_per_page' ) )
 185                  { // use blog default
 186                      $posts = $Blog->get_setting( 'posts_per_page' );
 187                  }
 188              }
 189              else
 190              {
 191                  // Does the pathinfo end with a / or a ; ?
 192                  $last_char = substr( $path_string, -1 );
 193                  $last_part = $path_elements[count( $path_elements )-1];
 194                  $last_len  = strlen( $last_part );
 195                  if( ( $last_char == '-' && ( ! $tags_dash_fix || $last_len != 40 ) ) || $last_char == ':'|| $last_char == ';' )
 196                  {    // - : or ; -> We'll consider this to be a tag page
 197                      $tag = substr( $last_part, 0, -1 );
 198                      $tag = urldecode($tag);
 199                      $tag = strip_tags($tag);    // security
 200                      // pre_dump( $tag );
 201  
 202                      // # of posts per page:
 203                      if( ! $posts = $Blog->get_setting( 'tag_posts_per_page' ) )
 204                      { // use blog default
 205                          $posts = $Blog->get_setting( 'posts_per_page' );
 206                      }
 207                  }
 208                  elseif( ( $tags_dash_fix && $last_char == '-' && $last_len == 40 ) || $last_char != '/' )
 209                  {    // NO ENDING SLASH or ends with a dash, is 40 chars long and $tags_dash_fix is true
 210                      // -> We'll consider this to be a ref to a post.
 211                      $Debuglog->add( 'We consider this o be a ref to a post - last char: '.$last_char, 'params' );
 212  
 213                      // Set a lot of defaults as if we had received a complex URL:
 214                      $m = '';
 215                      $more = 1; // Display the extended entries' text
 216                      $c = 1;    // Display comments
 217                      $tb = 1;   // Display trackbacks
 218                      $pb = 1;   // Display pingbacks
 219  
 220                      if( preg_match( '#^p([0-9]+)$#', $last_part, $req_post ) )
 221                      { // The last param is of the form p000
 222                          // echo 'post number';
 223                          $p = $req_post[1];        // Post to display
 224                      }
 225                      else
 226                      { // Last param is a string, we'll consider this to be a post urltitle
 227                          $title = $last_part;
 228                          // echo 'post title : ', $title;
 229                      }
 230                  }
 231                  else
 232                  {    // ENDING SLASH -> we are looking for a daterange OR a chapter:
 233                      $Debuglog->add( 'Last part: '.$last_part , 'params' );
 234                      // echo $last_part;
 235                      if( preg_match( '|^w?[0-9]+$|', $last_part ) )
 236                      { // Last part is a number or a "week" number:
 237                          $i=0;
 238                          $Debuglog->add( 'Last part is a number or a "week" number: '.$path_elements[$i] , 'params' );
 239                          // echo $path_elements[$i];
 240                          if( isset( $path_elements[$i] ) )
 241                          {
 242                              if( is_numeric( $path_elements[$i] ) )
 243                              { // We'll consider this to be the year
 244                                  $m = $path_elements[$i++];
 245                                  $Debuglog->add( 'Setting year from extra path info. $m=' . $m , 'params' );
 246  
 247                                  // Also use the prefered posts per page for archives (may be NULL, in which case the blog default will be used later on)
 248                                  if( ! $posts = $Blog->get_setting( 'archive_posts_per_page' ) )
 249                                  { // use blog default
 250                                      $posts = $Blog->get_setting( 'posts_per_page' );
 251                                  }
 252  
 253                                  if( isset( $path_elements[$i] ) && is_numeric( $path_elements[$i] ) )
 254                                  { // We'll consider this to be the month
 255                                      $m .= $path_elements[$i++];
 256                                      $Debuglog->add( 'Setting month from extra path info. $m=' . $m , 'params' );
 257  
 258                                      if( isset( $path_elements[$i] ) && is_numeric( $path_elements[$i] ) )
 259                                      { // We'll consider this to be the day
 260                                          $m .= $path_elements[$i++];
 261                                          $Debuglog->add( 'Setting day from extra path info. $m=' . $m , 'params' );
 262                                      }
 263                                  }
 264                                  elseif( isset( $path_elements[$i] ) && substr( $path_elements[$i], 0, 1 ) == 'w' )
 265                                  { // We consider this a week number
 266                                      $w = substr( $path_elements[$i], 1, 2 );
 267                                  }
 268                              }
 269                              else
 270                              {    // We did not get a number/year...
 271                                  $disp = '404';
 272                                  $disp_detail = '404-malformed_url-missing_year';
 273                              }
 274                          }
 275                      }
 276                      elseif( preg_match( '|^[A-Za-z0-9\-_]+$|', $last_part ) )    // UNDERSCORES for catching OLD URLS!!!
 277                      {    // We are pointing to a chapter/category:
 278                          $ChapterCache = & get_ChapterCache();
 279                          /**
 280                           * @var Chapter
 281                           */
 282                          $Chapter = & $ChapterCache->get_by_urlname( $last_part, false );
 283                          if( empty( $Chapter ) )
 284                          {    // We could not match a chapter...
 285                              // We are going to consider this to be a post title with a misplaced trailing slash.
 286                              // That happens when upgrading from WP for example.
 287                              $title = $last_part; // Will be sought later
 288                              $already_looked_into_chapters = true;
 289                          }
 290                          else
 291                          {    // We could match a chapter from the extra path:
 292                              $cat = $Chapter->ID;
 293                              // Also use the prefered posts per page for a cat
 294                              if( ! $posts = $Blog->get_setting( 'chapter_posts_per_page' ) )
 295                              { // use blog default
 296                                  $posts = $Blog->get_setting( 'posts_per_page' );
 297                              }
 298                              $disp = 'posts';
 299                          }
 300                      }
 301                      else
 302                      {    // We did not get anything we can decode...
 303                          // echo 'neither number nor cat';
 304                          $disp = '404';
 305                          $disp_detail = '404-malformed_url-bad_char';
 306                      }
 307                  }
 308              }
 309          }
 310  
 311      }
 312  }
 313  
 314  
 315  /*
 316   * ____________________________ Query params ____________________________
 317   *
 318   * Note: if the params have been set by the extra-path-info above, param() will not touch them.
 319   */
 320  param( 'p', 'integer', '', true );              // Specific post number to display
 321  param( 'title', 'string', '', true );                        // urtitle of post to display
 322  param( 'redir', 'string', 'yes', false );                // Do we allow redirection to canonical URL? (allows to force a 'single post' URL for commenting)
 323  param( 'preview', 'integer', 0, true );         // Is this preview ?
 324  param( 'stats', 'integer', 0 );                                    // Deprecated but might still be used by spambots
 325  
 326  
 327  
 328  // Front page detection & selection should probably occur here.
 329  
 330  
 331  
 332  /*
 333   * ____________________________ Get specific Item if requested ____________________________
 334   */
 335  if( !empty($p) || !empty($title) )
 336  { // We are going to display a single post
 337      $title = rawurldecode($title);
 338      // Make sure the single post we're requesting (still) exists:
 339      $ItemCache = & get_ItemCache();
 340      if( !empty($p) )
 341      {    // Get from post ID:
 342          $Item = & $ItemCache->get_by_ID( $p, false );
 343      }
 344      else
 345      {    // Get from post title:
 346          $orig_title = $title;
 347          // Convert all special chars to -
 348          $title = preg_replace( '/[^A-Za-z0-9_]/', '-', $title );
 349          $Item = & $ItemCache->get_by_urltitle( $title, false, false );
 350  
 351          if( ( !empty( $Item ) ) && ( $Item !== false ) && (! $Item->is_part_of_blog( $blog ) ) )
 352          { // We have found an Item object, but it doesn't belong to the current blog!
 353              unset($Item);
 354          }
 355  
 356          if( empty($Item) && substr($title, -1) == '-' )
 357          { // Try lookup by removing last invalid char, which might have been e.g. ">"
 358              $Item = $ItemCache->get_by_urltitle(substr($title, 0, -1), false, false);
 359          }
 360      }
 361      if( empty( $Item ) )
 362      {    // Post doesn't exist!
 363  
 364          // fp> TODO: ->viewing_allowed() for draft, private, protected and deprecated...
 365  
 366          $title_fallback = false;
 367          $tag_fallback = ( $tags_dash_fix && substr( $orig_title, -1 ) == '-' && strlen( $orig_title ) == 40 );
 368  
 369          if( ! $tag_fallback && !empty($title) && empty($already_looked_into_chapters) )
 370          {    // Let's try to fall back to a category/chapter...
 371              $ChapterCache = & get_ChapterCache();
 372              /**
 373               * @var Chapter
 374               */
 375              $Chapter = & $ChapterCache->get_by_urlname( $title, false );
 376              if( !empty( $Chapter ) )
 377              {    // We could match a chapter from the extra path:
 378                  $cat = $Chapter->ID;
 379                  $title_fallback = true;
 380                  $title = NULL;
 381                  // Also use the prefered posts per page for a cat
 382                  if( ! $posts = $Blog->get_setting( 'chapter_posts_per_page' ) )
 383                  { // use blog default
 384                      $posts = $Blog->get_setting( 'posts_per_page' );
 385                  }
 386              }
 387          }
 388  
 389          if( !empty($title) )
 390          {    // Let's try to fall back to a tag...
 391              if( $tag_fallback )
 392              {
 393                  $title = substr( $orig_title, 0, -1 );
 394              }
 395              if( $Blog->get_tag_post_count( $title ) )
 396              { // We could match a tag from the extra path:
 397                  $tag = $title;
 398                  $title_fallback = true;
 399                  $title = NULL;
 400              }
 401          }
 402  
 403          if( ! $title_fallback )
 404          {    // Let's try to fall back to a help slug...
 405              $SlugCache = & get_SlugCache();
 406              $Slug = & $SlugCache->get_by_name( $title, false, false );
 407              if( ! empty($Slug) && $Slug->get( 'type' ) == 'help' )
 408              { // We could match a help slug from the extra path:
 409                  $disp = 'help';
 410                  $title_fallback = true;
 411                  $title = NULL;
 412              }
 413          }
 414  
 415  /*    fp> The following is alternative code for filtering out index.php or blog1.php but this should not be needed
 416                  since I have re-enabled (a new version of) $pagenow removal earlier in this file.
 417          if( ! $title_fallback && $orig_title == $pagenow )
 418          {    // We are actually searching for something named after the PHP filename!
 419              // Example: blog1.php
 420              // Consider this as a request for the homepage:
 421              // pre_dump( '', $title, $orig_title, $pagenow, $disp );
 422              // Already set: $disp = 'posts';
 423              $title_fallback = true;
 424              $title = NULL;
 425          }
 426  */
 427  
 428          if( ! $title_fallback )
 429          {    // We were not able to fallback to anything meaningful:
 430              $disp = '404';
 431              $disp_detail = '404-post_not_found';
 432          }
 433      }
 434  }
 435  
 436  
 437  /*
 438   * ____________________________ "Clean up" the request ____________________________
 439   *
 440   * Make sure that:
 441   * 1) disp is set to "single" if single post requested
 442   * 2) URL is canonical if:
 443   *    - some content was requested in a weird/deprecated way
 444   *    - or if content identifiers have changed
 445   */
 446  if( $stats || $disp == 'stats' )
 447  {    // This used to be a spamfest...
 448      require $skins_path.'_410_stats_gone.main.php'; // error & exit
 449      // EXIT.
 450  }
 451  elseif( !empty($preview) )
 452  {    // Preview
 453      $disp = 'single';
 454      // Consider this as an admin hit!
 455      $Hit->hit_type = 'admin';
 456  }
 457  elseif( $disp == 'posts' && !empty($Item) )
 458  { // We are going to display a single post
 459      // if( in_array( $Item->ptyp_ID, $posttypes_specialtypes ) )
 460      if( $Item->ptyp_ID == 1000 )
 461      {
 462          $disp = 'page';
 463      }
 464      else
 465      {
 466          $disp = 'single';
 467      }
 468  
 469      // fp> note: the redirecting code that was here moved to skin_init() with the other redirecting code.
 470      // That feels more consistent and may also allow some skins to handle redirects differently (framing?)
 471      // I hope I didn't screw that up... but it felt like the historical reasons for this to be here no longer applied.
 472  }
 473  elseif( ( ( $disp == 'page' ) || ( $disp == 'single' ) ) && empty( $Item ) )
 474  { // 'page' and 'single' are not valid display params if $Item is not set
 475      // Note: The 'preview' action is the only one exception, but that is handled above in this if statement
 476      $disp = '404';
 477      $disp_detail = '404-post_not_found';
 478  }
 479  
 480  
 481  /*
 482   * ______________________ DETERMINE WHICH SKIN TO USE FOR DISPLAY _______________________
 483   */
 484  
 485  // Check if a temporary skin has been requested (used for RSS syndication for example):
 486  param( 'tempskin', 'string', '', true );
 487  if( !empty( $tempskin ) )
 488  { // This will be handled like any other skin:
 489      // TODO: maybe restrict that to authorized users
 490      $skin = $tempskin;
 491  }
 492  
 493  if( isset( $skin ) )
 494  {    // A skin has been requested by folder_name (url or stub):
 495  
 496      // Check validity of requested skin name:
 497      if( preg_match( '~([^-A-Za-z0-9._]|\.\.)~', $skin ) )
 498      {
 499          debug_die( 'The requested skin name is invalid.' );
 500      }
 501  
 502      $SkinCache = & get_SkinCache();
 503      $Skin = & $SkinCache->new_obj( NULL, $skin );
 504  
 505      if( $Skin->type == 'feed' )
 506      {    // Check if we actually allow the display of the feed; last chance to revert to 404 displayed in default skin.
 507          // Note: Skins with the type "feed" can always be accessed, even when they're not installed.
 508          if( ( $disp == 'posts' && $Blog->get_setting('feed_content') == 'none' ) ||
 509              ( $disp == 'comments' && $Blog->get_setting('comment_feed_content') == 'none' ) )
 510          { // We don't want to provide feeds; revert to 404!
 511              unset( $skin );
 512              unset( $Skin );
 513              $disp = '404';
 514              $disp_detail = '404-feeds-disabled';
 515          }
 516      }
 517      elseif( $Skin->type == 'sitemap' )
 518      {    // Check if we actually allow the display of sitemaps.
 519          // Note: Skins with the type "sitemap" can always be accessed, even when they're not installed.
 520          if( ! $Blog->get_setting('enable_sitemaps') )
 521          { // We don't want to show this sitemap, revert to error 404:
 522              unset( $skin );
 523              unset( $Skin );
 524              $disp = '404';
 525              $disp_detail = '404-sitemaps-disabled';
 526          }
 527      }
 528      elseif( skin_exists( $skin ) && ! skin_installed( $skin ) )
 529      {    // The requested skin is not a feed skin and exists in the file system, but isn't installed:
 530          debug_die( sprintf( T_( 'The skin [%s] is not installed on this system.' ), htmlspecialchars( $skin ) ) );
 531      }
 532      elseif( ! empty( $tempskin ) )
 533      { // By definition, we want to see the temporary skin (if we don't use feedburner... )
 534          $redir = 'no';
 535      }
 536  }
 537  
 538  $blog_skin_ID = $Blog->get_skin_ID();
 539  if( !isset( $skin ) && !empty( $blog_skin_ID ) )    // Note: if $skin is set to '', then we want to do a "no skin" display
 540  { // Use default skin from the database
 541      $SkinCache = & get_SkinCache();
 542      $Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
 543      $skin = $Skin->folder;
 544  }
 545  
 546  // Because a lot of bloggers will delete skins, we have to make this fool proof with extra checking:
 547  if( !empty( $skin ) && !skin_exists( $skin ) )
 548  { // We want to use a skin, but it doesn't exist!
 549      $err_msg = sprintf( T_('The skin [%s] set for blog [%s] does not exist. It must be properly set in the <a %s>blog properties</a> or properly overriden in a stub file.'),
 550          htmlspecialchars($skin),
 551          $Blog->dget('shortname'),
 552          'href="'.$admin_url.'?ctrl=coll_settings&amp;tab=skin&amp;blog='.$Blog->ID.'"' );
 553      debug_die( $err_msg );
 554  }
 555  
 556  /*
 557   * _______________ Name request/transaction for performance logging ________________
 558   *
 559   * A this point, we know what the request/transaction is about and we can give it
 560   * a meaning ful name.
 561   */
 562  $request_transaction_name = $Blog->shortname;
 563  
 564  if( !empty($disp_detail) )
 565  {
 566      $request_transaction_name .= ':'.$disp_detail;
 567  }
 568  elseif( !empty($disp) )
 569  {
 570      $request_transaction_name .= ':'.$disp;
 571  }
 572  
 573  $Debuglog->add( 'Transaction name: '.$request_transaction_name, 'request' );
 574  // Let's name the transaction for proper APM reporting:
 575  apm_name_transaction( $request_transaction_name );
 576  
 577  
 578  $Timer->pause( '_BLOG_MAIN.inc');
 579  // LOG with APM:
 580  $Timer->log_duration( '_BLOG_MAIN.inc' );
 581  
 582  
 583  /*
 584   * _______________________________ READY TO DISPLAY _______________________________
 585   *
 586   * At this point $skin holds the name of the skin we want to use, or '' for no skin!
 587   */
 588  
 589  
 590  // Trigger plugin event:
 591  // fp> TODO: please doc with example of what this can be used for
 592  $Plugins->trigger_event( 'BeforeBlogDisplay', array('skin'=>$skin) );
 593  
 594  if( !empty( $skin ) )
 595  { // We want to display with a skin now:
 596      $Timer->resume( 'SKIN DISPLAY' );
 597  
 598      $Debuglog->add('Selected skin: '.$skin, 'skins' );
 599  
 600      // Instantiate PageCache:
 601      $Timer->resume( 'PageCache' );
 602      load_class( '_core/model/_pagecache.class.php', 'PageCache' );
 603      $PageCache = new PageCache( $Blog );
 604      // Check for cached content & Start caching if needed
 605      // Note: there are some redirects inside the skins themselves for canonical URLs,
 606      // If we have a cache hit, the redirect won't take place until the cache expires -- probably ok.
 607      // If we start collecting and a redirect happens, the collecting will just be lost and that's what we want.
 608      if( ! $PageCache->check() )
 609      {    // Cache miss, we have to generate:
 610          $Timer->pause( 'PageCache' );
 611  
 612          if( $skin_provided_by_plugin = skin_provided_by_plugin($skin) )
 613          {
 614              $Plugins->call_method( $skin_provided_by_plugin, 'DisplaySkin', $tmp_params = array('skin'=>$skin) );
 615          }
 616          else
 617          {
 618              // Path for the current skin:
 619              $ads_current_skin_path = $skins_path.$skin.'/';
 620  
 621              $disp_handlers = array(
 622                      '404'            => '404_not_found.main.php',
 623                      'activateinfo'   => 'activateinfo.main.php',
 624                      'arcdir'         => 'arcdir.main.php',
 625                      'catdir'         => 'catdir.main.php',
 626                      'comments'       => 'comments.main.php',
 627                      'feedback-popup' => 'feedback_popup.main.php',
 628                      'login'          => 'login.main.php',
 629                      'mediaidx'       => 'mediaidx.main.php',
 630                      'msgform'        => 'msgform.main.php',
 631                      'page'           => 'page.main.php',
 632                      'postidx'        => 'postidx.main.php',
 633                      'posts'          => 'posts.main.php',
 634                      'profile'        => 'profile.main.php',
 635                      'search'         => 'search.main.php',
 636                      'single'         => 'single.main.php',
 637                      'sitemap'        => 'sitemap.main.php',
 638                      'subs'           => 'subs.main.php',
 639                      'threads'        => 'threads.main.php',
 640                      'messages'       => 'messages.main.php',
 641                      'contacts'       => 'contacts.main.php',
 642                      'user'           => 'user.main.php',
 643                      'users'          => 'users.main.php',
 644                      'edit'           => 'edit.main.php',
 645                      'edit_comment'   => 'edit_comment.main.php',
 646                      'useritems'      => 'useritems.main.php',
 647                      'usercomments'   => 'usercomments.main.php',
 648                      // All others will default to index.main.php
 649                  );
 650  
 651              if( $disp == 'search' && ! file_exists( $ads_current_skin_path.'_item_block.inc.php' ) )
 652              {    // Skins from 2.x don't have '_item_block.inc.php' file, and there's no fallback file in /skins directory
 653                  // So we simply load the 'posts' disp handler
 654                  $disp = 'posts';
 655              }
 656  
 657              if( !empty($disp_handlers[$disp]) )
 658              {
 659                  if( file_exists( $disp_handler = $ads_current_skin_path.$disp_handlers[$disp] ) )
 660                  {    // The skin has a customized page handler for this display:
 661                      $Debuglog->add('blog_main: include '.rel_path_to_base($disp_handler).' (custom to this skin)', 'skins' );
 662                      require $disp_handler;
 663                  }
 664                  elseif( file_exists( $disp_handler = $skins_path.$disp_handlers[$disp] ) )
 665                  {    // Skins have a general page handler for this display:
 666                      $Debuglog->add('blog_main: include '.rel_path_to_base($disp_handler).' (for CSS include -- added in v 4.1)', 'skins' );
 667                      require $disp_handler;
 668                  }
 669                  elseif( $disp_handlers[$disp] == 'posts.main.php' && file_exists( $disp_handler = $ads_current_skin_path.'items.main.php' ) )
 670                  {    // Compatibility with skins < 2.2.0
 671                      $Debuglog->add('blog_main: include '.rel_path_to_base($disp_handler).' (compat with skins < 2.2.0)', 'skins' );
 672                      require $disp_handler;
 673                  }
 674                  elseif( $disp_handlers[$disp] == 'comments.main.php' && file_exists( $disp_handler = $ads_current_skin_path.'latestcom.tpl.php' ) )
 675                  {    // Compatibility with skins < 2.2.0
 676                      $Debuglog->add('blog_main: include '.rel_path_to_base($disp_handler).' (compat with skins < 2.2.0)', 'skins' );
 677                      require $disp_handler;
 678                  }
 679                  elseif( $disp_handlers[$disp] == 'feedback_popup.main.php' && file_exists( $disp_handler = $ads_current_skin_path.'feedback_popup.tpl.php' ) )
 680                  {    // Compatibility with skins < 2.2.0
 681                      $Debuglog->add('blog_main: include '.rel_path_to_base($disp_handler).' (compat with skins < 2.2.0)', 'skins' );
 682                      require $disp_handler;
 683                  }
 684                  else
 685                  {    // Use the default handler from the skins dir:
 686                      $Debuglog->add('blog_main: include '.rel_path_to_base($ads_current_skin_path.'index.main.php').' (default handler)', 'skins' );
 687                      require $ads_current_skin_path.'index.main.php';
 688                  }
 689              }
 690              else
 691              {    // Use the default handler from the skins dir:
 692                  $Debuglog->add('blog_main: include '.rel_path_to_base($ads_current_skin_path.'index.main.php').' (default index handler)', 'skins' );
 693                  require $ads_current_skin_path.'index.main.php';
 694              }
 695          }
 696  
 697          // Save collected cached data if needed:
 698          $PageCache->end_collect();
 699      }
 700      $Timer->pause( 'PageCache' );
 701  
 702      $Timer->pause( 'SKIN DISPLAY' );
 703      // LOG with APM:
 704      $Timer->log_duration( 'SKIN DISPLAY' );
 705  
 706      // We probably don't want to return to the caller if we have displayed a skin...
 707      // That is useful if the caller implements a custom display but we still use skins for RSS/ Atom etc..
 708      exit(0);
 709  }
 710  else
 711  {    // We don't use a skin. Hopefully the caller will do some displaying.
 712      // Set a few vars with default values, just in case...
 713      $ads_current_skin_path = $htsrv_path;
 714  
 715      // We'll just return to the caller now... (if we have not used a skin, the caller should do the display after this)
 716  }
 717  
 718  ?>

title

Description

title

Description

title

Description

title

title

Body