Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_module.php

Zuletzt modifiziert: 09.10.2024, 12:50 - Dateigröße: 22.24 KiB


 001  <?php
 002  /**
 003  *
 004  * @package phpBB3
 005  * @version $Id$
 006  * @copyright (c) 2005 phpBB Group
 007  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 008  *
 009  */
 010   
 011  /**
 012  * @ignore
 013  */
 014  if (!defined('IN_PHPBB'))
 015  {
 016      exit;
 017  }
 018   
 019  /**
 020  * Class handling all types of 'plugins' (a future term)
 021  * @package phpBB3
 022  */
 023  class p_master
 024  {
 025      var $p_id;
 026      var $p_class;
 027      var $p_name;
 028      var $p_mode;
 029      var $p_parent;
 030   
 031      var $active_module = false;
 032      var $active_module_row_id = false;
 033      var $acl_forum_id = false;
 034      var $module_ary = array();
 035   
 036      /**
 037      * List modules
 038      *
 039      * This creates a list, stored in $this->module_ary of all available
 040      * modules for the given class (ucp, mcp and acp). Additionally
 041      * $this->module_y_ary is created with indentation information for
 042      * displaying the module list appropriately. Only modules for which
 043      * the user has access rights are included in these lists.
 044      */
 045      function list_modules($p_class)
 046      {
 047          global $auth, $db, $user, $cache;
 048          global $config, $phpbb_root_path, $phpEx;
 049   
 050          // Sanitise for future path use, it's escaped as appropriate for queries
 051          $this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class));
 052   
 053          // Get cached modules
 054          if (($this->module_cache = $cache->get('_modules_' . $this->p_class)) === false)
 055          {
 056              // Get modules
 057              $sql = 'SELECT *
 058                  FROM ' . MODULES_TABLE . "
 059                  WHERE module_class = '" . $db->sql_escape($this->p_class) . "'
 060                  ORDER BY left_id ASC";
 061              $result = $db->sql_query($sql);
 062              
 063              $rows = array();
 064              while ($row = $db->sql_fetchrow($result))
 065              {
 066                  $rows[$row['module_id']] = $row;
 067              }
 068              $db->sql_freeresult($result);
 069   
 070              $this->module_cache = array();
 071              foreach ($rows as $module_id => $row)
 072              {
 073                  $this->module_cache['modules'][] = $row;
 074                  $this->module_cache['parents'][$row['module_id']] = $this->get_parents($row['parent_id'], $row['left_id'], $row['right_id'], $rows);
 075              }
 076              unset($rows);
 077   
 078              $cache->put('_modules_' . $this->p_class, $this->module_cache);
 079          }
 080   
 081          if (empty($this->module_cache))
 082          {
 083              $this->module_cache = array('modules' => array(), 'parents' => array());
 084          }
 085   
 086          // We "could" build a true tree with this function - maybe mod authors want to use this...
 087          // Functions for traversing and manipulating the tree are not available though
 088          // We might re-structure the module system to use true trees in 3.2.x...
 089          // $tree = $this->build_tree($this->module_cache['modules'], $this->module_cache['parents']);
 090   
 091          // Clean up module cache array to only let survive modules the user can access
 092          $right_id = false;
 093          foreach ($this->module_cache['modules'] as $key => $row)
 094          {
 095              // Not allowed to view module?
 096              if (!$this->module_auth($row['module_auth']))
 097              {
 098                  unset($this->module_cache['modules'][$key]);
 099                  continue;
 100              }
 101   
 102              // Category with no members, ignore
 103              if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id']))
 104              {
 105                  unset($this->module_cache['modules'][$key]);
 106                  continue;
 107              }
 108   
 109              // Skip branch
 110              if ($right_id !== false)
 111              {
 112                  if ($row['left_id'] < $right_id)
 113                  {
 114                      unset($this->module_cache['modules'][$key]);
 115                      continue;
 116                  }
 117                  
 118                  $right_id = false;
 119              }
 120   
 121              // Not enabled?
 122              if (!$row['module_enabled'])
 123              {
 124                  // If category is disabled then disable every child too
 125                  unset($this->module_cache['modules'][$key]);
 126                  $right_id = $row['right_id'];
 127                  continue;
 128              }
 129          }
 130   
 131          // Re-index (this is needed, else we are not able to array_slice later)
 132          $this->module_cache['modules'] = array_merge($this->module_cache['modules']);
 133   
 134          // Include MOD _info files for populating language entries within the menus
 135          $this->add_mod_info($this->p_class);
 136   
 137          // Now build the module array, but exclude completely empty categories...
 138          $right_id = false;
 139          $names = array();
 140   
 141          foreach ($this->module_cache['modules'] as $key => $row)
 142          {
 143              // Skip branch
 144              if ($right_id !== false)
 145              {
 146                  if ($row['left_id'] < $right_id)
 147                  {
 148                      continue;
 149                  }
 150                  
 151                  $right_id = false;
 152              }
 153   
 154              // Category with no members on their way down (we have to check every level)
 155              if (!$row['module_basename'])
 156              {
 157                  $empty_category = true;
 158   
 159                  // We go through the branch and look for an activated module
 160                  foreach (array_slice($this->module_cache['modules'], $key + 1) as $temp_row)
 161                  {
 162                      if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id'])
 163                      {
 164                          // Module there
 165                          if ($temp_row['module_basename'] && $temp_row['module_enabled'])
 166                          {
 167                              $empty_category = false;
 168                              break;
 169                          }
 170                          continue;
 171                      }
 172                      break;
 173                  }
 174   
 175                  // Skip the branch
 176                  if ($empty_category)
 177                  {
 178                      $right_id = $row['right_id'];
 179                      continue;
 180                  }
 181              }
 182   
 183              $depth = sizeof($this->module_cache['parents'][$row['module_id']]);
 184   
 185              // We need to prefix the functions to not create a naming conflict
 186   
 187              // Function for building 'url_extra'
 188              $url_func = '_module_' . $row['module_basename'] . '_url';
 189   
 190              // Function for building the language name
 191              $lang_func = '_module_' . $row['module_basename'] . '_lang';
 192   
 193              // Custom function for calling parameters on module init (for example assigning template variables)
 194              $custom_func = '_module_' . $row['module_basename'];
 195   
 196              $names[$row['module_basename'] . '_' . $row['module_mode']][] = true;
 197              
 198              $module_row = array(
 199                  'depth'        => $depth,
 200   
 201                  'id'        => (int) $row['module_id'],
 202                  'parent'    => (int) $row['parent_id'],
 203                  'cat'        => ($row['right_id'] > $row['left_id'] + 1) ? true : false,
 204   
 205                  'is_duplicate'    => ($row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false,
 206   
 207                  'name'        => (string) $row['module_basename'],
 208                  'mode'        => (string) $row['module_mode'],
 209                  'display'    => (int) $row['module_display'],
 210   
 211                  'url_extra'    => (function_exists($url_func)) ? $url_func($row['module_mode'], $row) : '',
 212                  
 213                  'lang'        => ($row['module_basename'] && function_exists($lang_func)) ? $lang_func($row['module_mode'], $row['module_langname']) : ((!empty($user->lang[$row['module_langname']])) ? $user->lang[$row['module_langname']] : $row['module_langname']),
 214                  'langname'    => $row['module_langname'],
 215   
 216                  'left'        => $row['left_id'],
 217                  'right'        => $row['right_id'],
 218              );
 219   
 220              if (function_exists($custom_func))
 221              {
 222                  $custom_func($row['module_mode'], $module_row);
 223              }
 224   
 225              $this->module_ary[] = $module_row;
 226          }
 227   
 228          unset($this->module_cache['modules'], $names);
 229      }
 230   
 231      /**
 232      * Check if a certain main module is accessible/loaded
 233      * By giving the module mode you are able to additionally check for only one mode within the main module
 234      *
 235      * @param string $module_basename The module base name, for example logs, reports, main (for the mcp).
 236      * @param mixed $module_mode The module mode to check. If provided the mode will be checked in addition for presence.
 237      *
 238      * @return bool Returns true if module is loaded and accessible, else returns false
 239      */
 240      function loaded($module_basename, $module_mode = false)
 241      {
 242          if (empty($this->loaded_cache))
 243          {
 244              $this->loaded_cache = array();
 245   
 246              foreach ($this->module_ary as $row)
 247              {
 248                  if (!$row['name'])
 249                  {
 250                      continue;
 251                  }
 252   
 253                  if (!isset($this->loaded_cache[$row['name']]))
 254                  {
 255                      $this->loaded_cache[$row['name']] = array();
 256                  }
 257   
 258                  if (!$row['mode'])
 259                  {
 260                      continue;
 261                  }
 262   
 263                  $this->loaded_cache[$row['name']][$row['mode']] = true;
 264              }
 265          }
 266   
 267          if ($module_mode === false)
 268          {
 269              return (isset($this->loaded_cache[$module_basename])) ? true : false;
 270          }
 271   
 272          return (!empty($this->loaded_cache[$module_basename][$module_mode])) ? true : false;
 273      }
 274   
 275      /**
 276      * Check module authorisation
 277      */
 278      function module_auth($module_auth, $forum_id = false)
 279      {
 280          global $auth, $config;
 281   
 282          $module_auth = trim($module_auth);
 283   
 284          // Generally allowed to access module if module_auth is empty
 285          if (!$module_auth)
 286          {
 287              return true;
 288          }
 289   
 290          // With the code below we make sure only those elements get eval'd we really want to be checked
 291          preg_match_all('/(?:
 292              "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"         |
 293              \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'     |
 294              [(),]                                  |
 295              [^\s(),]+)/x', $module_auth, $match);
 296   
 297          $tokens = $match[0];
 298          for ($i = 0, $size = sizeof($tokens); $i < $size; $i++)
 299          {
 300              $token = &$tokens[$i];
 301   
 302              switch ($token)
 303              {
 304                  case ')':
 305                  case '(':
 306                  case '&&':
 307                  case '||':
 308                  case ',':
 309                  break;
 310   
 311                  default:
 312                      if (!preg_match('#(?:acl_([a-z_]+)(,\$id)?)|(?:\$id)|(?:aclf_([a-z_]+))|(?:cfg_([a-z_]+))|(?:request_([a-z_]+))#', $token))
 313                      {
 314                          $token = '';
 315                      }
 316                  break;
 317              }
 318          }
 319   
 320          $module_auth = implode(' ', $tokens);
 321   
 322          // Make sure $id seperation is working fine
 323          $module_auth = str_replace(' , ', ',', $module_auth);
 324   
 325          $forum_id = ($forum_id === false) ? $this->acl_forum_id : $forum_id;
 326   
 327          $is_auth = false;
 328          eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z_]+)#', '#cfg_([a-z_]+)#', '#request_([a-z_]+)#'), array('(int) $auth->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) $auth->acl_getf_global(\'\\1\')', '(int) $config[\'\\1\']', '!empty($_REQUEST[\'\\1\'])'), $module_auth) . ');');
 329   
 330          return $is_auth;
 331      }
 332   
 333      /**
 334      * Set active module
 335      */
 336      function set_active($id = false, $mode = false)
 337      {
 338          $icat = false;
 339          $this->active_module = false;
 340   
 341          if (request_var('icat', ''))
 342          {
 343              $icat = $id;
 344              $id = request_var('icat', '');
 345          }
 346   
 347          $category = false;
 348          foreach ($this->module_ary as $row_id => $item_ary)
 349          {
 350              // If this is a module and it's selected, active
 351              // If this is a category and the module is the first within it, active
 352              // If this is a module and no mode selected, select first mode
 353              // If no category or module selected, go active for first module in first category
 354              if (
 355                  (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) ||
 356                  ($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat && $item_ary['display']) ||
 357                  (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) ||
 358                  (!$id && !$mode && !$item_ary['cat'] && $item_ary['display'])
 359                  )
 360              {
 361                  if ($item_ary['cat'])
 362                  {
 363                      $id = $icat;
 364                      $icat = false;
 365   
 366                      continue;
 367                  }
 368   
 369                  $this->p_id        = $item_ary['id'];
 370                  $this->p_parent    = $item_ary['parent'];
 371                  $this->p_name    = $item_ary['name'];
 372                  $this->p_mode     = $item_ary['mode'];
 373                  $this->p_left    = $item_ary['left'];
 374                  $this->p_right    = $item_ary['right'];
 375   
 376                  $this->module_cache['parents'] = $this->module_cache['parents'][$this->p_id];
 377                  $this->active_module = $item_ary['id'];
 378                  $this->active_module_row_id = $row_id;
 379   
 380                  break;
 381              }
 382              else if (($item_ary['cat'] && $item_ary['id'] === (int) $id) || ($item_ary['parent'] === $category && $item_ary['cat']))
 383              {
 384                  $category = $item_ary['id'];
 385              }
 386          }
 387      }
 388   
 389      /**
 390      * Loads currently active module
 391      *
 392      * This method loads a given module, passing it the relevant id and mode.
 393      */
 394      function load_active($mode = false, $module_url = false, $execute_module = true)
 395      {
 396          global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user;
 397   
 398          $module_path = $phpbb_root_path . 'includes/' . $this->p_class;
 399          $icat = request_var('icat', '');
 400   
 401          if ($this->active_module === false)
 402          {
 403              trigger_error('Module not accessible', E_USER_ERROR);
 404          }
 405   
 406          if (!class_exists("{$this->p_class}_$this->p_name"))
 407          {
 408              if (!file_exists("$module_path/{$this->p_class}_$this->p_name.$phpEx"))
 409              {
 410                  trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR);
 411              }
 412   
 413              include("$module_path/{$this->p_class}_$this->p_name.$phpEx");
 414   
 415              if (!class_exists("{$this->p_class}_$this->p_name"))
 416              {
 417                  trigger_error("Module file $module_path/{$this->p_class}_$this->p_name.$phpEx does not contain correct class [{$this->p_class}_$this->p_name]", E_USER_ERROR);
 418              }
 419   
 420              if (!empty($mode))
 421              {
 422                  $this->p_mode = $mode;
 423              }
 424   
 425              // Create a new instance of the desired module ... if it has a
 426              // constructor it will of course be executed
 427              $instance = "{$this->p_class}_$this->p_name";
 428   
 429              $this->module = new $instance($this);
 430   
 431              // We pre-define the action parameter we are using all over the place
 432              if (defined('IN_ADMIN'))
 433              {
 434                  // Is first module automatically enabled a duplicate and the category not passed yet?
 435                  if (!$icat && $this->module_ary[$this->active_module_row_id]['is_duplicate'])
 436                  {
 437                      $icat = $this->module_ary[$this->active_module_row_id]['parent'];
 438                  }
 439   
 440                  // Not being able to overwrite ;)
 441                  $this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$this->p_name}") . (($icat) ? '&amp;icat=' . $icat : '') . "&amp;mode={$this->p_mode}";
 442              }
 443              else
 444              {
 445                  // If user specified the module url we will use it...
 446                  if ($module_url !== false)
 447                  {
 448                      $this->module->u_action = $module_url;
 449                  }
 450                  else
 451                  {
 452                      $this->module->u_action = $phpbb_root_path . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name'];
 453                  }
 454   
 455                  $this->module->u_action = append_sid($this->module->u_action, "i={$this->p_name}") . (($icat) ? '&amp;icat=' . $icat : '') . "&amp;mode={$this->p_mode}";
 456              }
 457   
 458              // Add url_extra parameter to u_action url
 459              if (!empty($this->module_ary) && $this->active_module !== false && $this->module_ary[$this->active_module_row_id]['url_extra'])
 460              {
 461                  $this->module->u_action .= $this->module_ary[$this->active_module_row_id]['url_extra'];
 462              }
 463   
 464              // Assign the module path for re-usage
 465              $this->module->module_path = $module_path . '/';
 466   
 467              // Execute the main method for the new instance, we send the module id and mode as parameters
 468              // Users are able to call the main method after this function to be able to assign additional parameters manually
 469              if ($execute_module)
 470              {
 471                  $this->module->main($this->p_name, $this->p_mode);
 472              }
 473   
 474              return;
 475          }
 476      }
 477   
 478      /**
 479      * Appending url parameter to the currently active module.
 480      *
 481      * This function is called for adding specific url parameters while executing the current module.
 482      * It is doing the same as the _module_{name}_url() function, apart from being able to be called after
 483      * having dynamically parsed specific parameters. This allows more freedom in choosing additional parameters.
 484      * One example can be seen in /includes/mcp/mcp_notes.php - $this->p_master->adjust_url() call.
 485      *
 486      * @param string $url_extra Extra url parameters, e.g.: &amp;u=$user_id
 487      *
 488      */
 489      function adjust_url($url_extra)
 490      {
 491          if (empty($this->module_ary[$this->active_module_row_id]))
 492          {
 493              return;
 494          }
 495   
 496          $row = &$this->module_ary[$this->active_module_row_id];
 497   
 498          // We check for the same url_extra in $row['url_extra'] to overcome doubled additions...
 499          if (strpos($row['url_extra'], $url_extra) === false)
 500          {
 501              $row['url_extra'] .= $url_extra;
 502          }
 503      }
 504   
 505      /**
 506      * Check if a module is active
 507      */
 508      function is_active($id, $mode = false)
 509      {
 510          // If we find a name by this id and being enabled we have our active one...
 511          foreach ($this->module_ary as $row_id => $item_ary)
 512          {
 513              if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && $item_ary['display'])
 514              {
 515                  if ($mode === false || $mode === $item_ary['mode'])
 516                  {
 517                      return true;
 518                  }
 519              }
 520          }
 521   
 522          return false;
 523      }
 524   
 525      /**
 526      * Get parents
 527      */
 528      function get_parents($parent_id, $left_id, $right_id, &$all_parents)
 529      {
 530          global $db;
 531   
 532          $parents = array();
 533   
 534          if ($parent_id > 0)
 535          {
 536              foreach ($all_parents as $module_id => $row)
 537              {
 538                  if ($row['left_id'] < $left_id && $row['right_id'] > $right_id)
 539                  {
 540                      $parents[$module_id] = $row['parent_id'];
 541                  }
 542   
 543                  if ($row['left_id'] > $left_id)
 544                  {
 545                      break;
 546                  }
 547              }
 548          }
 549   
 550          return $parents;
 551      }
 552   
 553      /**
 554      * Get tree branch
 555      */
 556      function get_branch($left_id, $right_id, $remaining)
 557      {
 558          $branch = array();
 559   
 560          foreach ($remaining as $key => $row)
 561          {
 562              if ($row['left_id'] > $left_id && $row['left_id'] < $right_id)
 563              {
 564                  $branch[] = $row;
 565                  continue;
 566              }
 567              break;
 568          }
 569   
 570          return $branch;
 571      }
 572   
 573      /**
 574      * Build true binary tree from given array
 575      * Not in use
 576      */
 577      function build_tree(&$modules, &$parents)
 578      {
 579          $tree = array();
 580   
 581          foreach ($modules as $row)
 582          {
 583              $branch = &$tree;
 584   
 585              if ($row['parent_id'])
 586              {
 587                  // Go through the tree to find our branch
 588                  $parent_tree = $parents[$row['module_id']];
 589   
 590                  foreach ($parent_tree as $id => $value)
 591                  {
 592                      if (!isset($branch[$id]) && isset($branch['child']))
 593                      {
 594                          $branch = &$branch['child'];
 595                      }
 596                      $branch = &$branch[$id];
 597                  }
 598                  $branch = &$branch['child'];
 599              }
 600   
 601              $branch[$row['module_id']] = $row;
 602              if (!isset($branch[$row['module_id']]['child']))
 603              {
 604                  $branch[$row['module_id']]['child'] = array();
 605              }
 606          }
 607   
 608          return $tree;
 609      }
 610   
 611      /**
 612      * Build navigation structure
 613      */
 614      function assign_tpl_vars($module_url)
 615      {
 616          global $template;
 617   
 618          $current_id = $right_id = false;
 619   
 620          // Make sure the module_url has a question mark set, effectively determining the delimiter to use
 621          $delim = (strpos($module_url, '?') === false) ? '?' : '&amp;';
 622   
 623          $current_padding = $current_depth = 0;
 624          $linear_offset     = 'l_block1';
 625          $tabular_offset = 't_block2';
 626   
 627          // Generate the list of modules, we'll do this in two ways ...
 628          // 1) In a linear fashion
 629          // 2) In a combined tabbed + linear fashion ... tabs for the categories
 630          //    and a linear list for subcategories/items
 631          foreach ($this->module_ary as $row_id => $item_ary)
 632          {
 633              // Skip hidden modules
 634              if (!$item_ary['display'])
 635              {
 636                  continue;
 637              }
 638   
 639              // Skip branch
 640              if ($right_id !== false)
 641              {
 642                  if ($item_ary['left'] < $right_id)
 643                  {
 644                      continue;
 645                  }
 646   
 647                  $right_id = false;
 648              }
 649   
 650              // Category with no members on their way down (we have to check every level)
 651              if (!$item_ary['name'])
 652              {
 653                  $empty_category = true;
 654   
 655                  // We go through the branch and look for an activated module
 656                  foreach (array_slice($this->module_ary, $row_id + 1) as $temp_row)
 657                  {
 658                      if ($temp_row['left'] > $item_ary['left'] && $temp_row['left'] < $item_ary['right'])
 659                      {
 660                          // Module there and displayed?
 661                          if ($temp_row['name'] && $temp_row['display'])
 662                          {
 663                              $empty_category = false;
 664                              break;
 665                          }
 666                          continue;
 667                      }
 668                      break;
 669                  }
 670   
 671                  // Skip the branch
 672                  if ($empty_category)
 673                  {
 674                      $right_id = $item_ary['right'];
 675                      continue;
 676                  }
 677              }
 678   
 679              // Select first id we can get
 680              if (!$current_id && (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id))
 681              {
 682                  $current_id = $item_ary['id'];
 683              }
 684   
 685              $depth = $item_ary['depth'];
 686   
 687              if ($depth > $current_depth)
 688              {
 689                  $linear_offset = $linear_offset . '.l_block' . ($depth + 1);
 690                  $tabular_offset = ($depth + 1 > 2) ? $tabular_offset . '.t_block' . ($depth + 1) : $tabular_offset;
 691              }
 692              else if ($depth < $current_depth)
 693              {
 694                  for ($i = $current_depth - $depth; $i > 0; $i--)
 695                  {
 696                      $linear_offset = substr($linear_offset, 0, strrpos($linear_offset, '.'));
 697                      $tabular_offset = ($i + $depth > 1) ? substr($tabular_offset, 0, strrpos($tabular_offset, '.')) : $tabular_offset;
 698                  }
 699              }
 700   
 701              $u_title = $module_url . $delim . 'i=' . (($item_ary['cat']) ? $item_ary['id'] : $item_ary['name'] . (($item_ary['is_duplicate']) ? '&amp;icat=' . $current_id : '') . '&amp;mode=' . $item_ary['mode']);
 702   
 703              // Was not allowed in categories before - /*!$item_ary['cat'] && */
 704              $u_title .= (isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : '';
 705   
 706              // Only output a categories items if it's currently selected
 707              if (!$depth || ($depth && (in_array($item_ary['parent'], array_values($this->module_cache['parents'])) || $item_ary['parent'] == $this->p_parent)))
 708              {
 709                  $use_tabular_offset = (!$depth) ? 't_block1' : $tabular_offset;
 710   
 711                  $tpl_ary = array(
 712                      'L_TITLE'        => $item_ary['lang'],
 713                      'S_SELECTED'    => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id) ? true : false,
 714                      'U_TITLE'        => $u_title
 715                  );
 716   
 717                  $template->assign_block_vars($use_tabular_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER)));
 718              }
 719   
 720              $tpl_ary = array(
 721                  'L_TITLE'        => $item_ary['lang'],
 722                  'S_SELECTED'    => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id) ? true : false,
 723                  'U_TITLE'        => $u_title
 724              );
 725   
 726              $template->assign_block_vars($linear_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER)));
 727   
 728              $current_depth = $depth;
 729          }
 730      }
 731   
 732      /**
 733      * Returns desired template name
 734      */
 735      function get_tpl_name()
 736      {
 737          return $this->module->tpl_name . '.html';
 738      }
 739   
 740      /**
 741      * Returns the desired page title
 742      */
 743      function get_page_title()
 744      {
 745          global $user;
 746   
 747          if (!isset($this->module->page_title))
 748          {
 749              return '';
 750          }
 751   
 752          return (isset($user->lang[$this->module->page_title])) ? $user->lang[$this->module->page_title] : $this->module->page_title;
 753      }
 754   
 755      /**
 756      * Load module as the current active one without the need for registering it
 757      */
 758      function load($class, $name, $mode = false)
 759      {
 760          $this->p_class = $class;
 761          $this->p_name = $name;
 762   
 763          // Set active module to true instead of using the id
 764          $this->active_module = true;
 765   
 766          $this->load_active($mode);
 767      }
 768   
 769      /**
 770      * Display module
 771      */
 772      function display($page_title, $display_online_list = true)
 773      {
 774          global $template, $user;
 775   
 776          // Generate the page
 777          if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
 778          {
 779              adm_page_header($page_title);
 780          }
 781          else
 782          {
 783              page_header($page_title, $display_online_list);
 784          }
 785   
 786          $template->set_filenames(array(
 787              'body' => $this->get_tpl_name())
 788          );
 789   
 790          if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
 791          {
 792              adm_page_footer();
 793          }
 794          else
 795          {
 796              page_footer();
 797          }
 798      }
 799   
 800      /**
 801      * Toggle whether this module will be displayed or not
 802      */
 803      function set_display($id, $mode = false, $display = true)
 804      {
 805          foreach ($this->module_ary as $row_id => $item_ary)
 806          {
 807              if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode))
 808              {
 809                  $this->module_ary[$row_id]['display'] = (int) $display;
 810              }
 811          }
 812      }
 813   
 814      /**
 815      * Add custom MOD info language file
 816      */
 817      function add_mod_info($module_class)
 818      {
 819          global $user, $phpEx;
 820   
 821          if (file_exists($user->lang_path . 'mods'))
 822          {
 823              $add_files = array();
 824   
 825              $dir = @opendir($user->lang_path . 'mods');
 826   
 827              if ($dir)
 828              {
 829                  while (($entry = readdir($dir)) !== false)
 830                  {
 831                      if (strpos($entry, 'info_' . strtolower($module_class) . '_') === 0 && substr(strrchr($entry, '.'), 1) == $phpEx)
 832                      {
 833                          $add_files[] = 'mods/' . substr(basename($entry), 0, -(strlen($phpEx) + 1));
 834                      }
 835                  }
 836                  closedir($dir);
 837              }
 838   
 839              if (sizeof($add_files))
 840              {
 841                  $user->add_lang($add_files);
 842              }
 843          }
 844      }
 845  }
 846   
 847  ?>