[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/ -> functions_module.php (source)

   1  <?php
   2  /** 
   3  *
   4  * @package phpBB3
   5  * @version $Id: functions_module.php,v 1.39 2006/10/19 13:54:47 acydburn Exp $
   6  * @copyright (c) 2005 phpBB Group 
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License 
   8  *
   9  */
  10  
  11  /**
  12  * Class handling all types of 'plugins' (a future term)
  13  * @package phpBB3
  14  */
  15  class p_master
  16  {
  17      var $p_id;
  18      var $p_class;
  19      var $p_name;
  20      var $p_mode;
  21      var $p_parent;
  22  
  23      var $active_module = false;
  24      var $acl_forum_id = false;
  25      var $module_ary = array();
  26  
  27      /**
  28      * List modules
  29      *
  30      * This creates a list, stored in $this->module_ary of all available
  31      * modules for the given class (ucp, mcp and acp). Additionally
  32      * $this->module_y_ary is created with indentation information for
  33      * displaying the module list appropriately. Only modules for which
  34      * the user has access rights are included in these lists.
  35      */
  36  	function list_modules($p_class)
  37      {
  38          global $auth, $db, $user, $cache;
  39          global $config, $phpbb_root_path, $phpEx;
  40  
  41          // Sanitise for future path use, it's escaped as appropriate for queries
  42          $this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class));
  43  
  44          // Get cached modules
  45          if (($this->module_cache = $cache->get('_modules_' . $this->p_class)) === false)
  46          {
  47              // Get modules
  48              $sql = 'SELECT *
  49                  FROM ' . MODULES_TABLE . "
  50                  WHERE module_class = '" . $db->sql_escape($this->p_class) . "'
  51                  ORDER BY left_id ASC";
  52              $result = $db->sql_query($sql);
  53              
  54              $rows = array();
  55              while ($row = $db->sql_fetchrow($result))
  56              {
  57                  $rows[$row['module_id']] = $row;
  58              }
  59              $db->sql_freeresult($result);
  60  
  61              $this->module_cache = array();
  62              foreach ($rows as $module_id => $row)
  63              {
  64                  $this->module_cache['modules'][] = $row;
  65                  $this->module_cache['parents'][$row['module_id']] = $this->get_parents($row['parent_id'], $row['left_id'], $row['right_id'], $rows);
  66              }
  67              unset($rows);
  68  
  69              $cache->put('_modules_' . $this->p_class, $this->module_cache);
  70          }
  71  
  72          // We "could" build a true tree with this function - maybe mod authors want to use this...
  73          // Functions for traversing and manipulating the tree are not available though
  74          // We might re-structure the module system to use true trees in 3.2.x...
  75          // $tree = $this->build_tree($this->module_cache['modules'], $this->module_cache['parents']);
  76  
  77          // Clean up module cache array to only let survive modules the user can access
  78          $right_id = false;
  79          foreach ($this->module_cache['modules'] as $key => $row)
  80          {
  81              // Not allowed to view module?
  82              if (!$this->module_auth($row['module_auth']))
  83              {
  84                  unset($this->module_cache['modules'][$key]);
  85                  continue;
  86              }
  87  
  88              // Category with no members, ignore
  89              if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id']))
  90              {
  91                  unset($this->module_cache['modules'][$key]);
  92                  continue;
  93              }
  94  
  95              // Skip branch
  96              if ($right_id !== false)
  97              {
  98                  if ($row['left_id'] < $right_id)
  99                  {
 100                      unset($this->module_cache['modules'][$key]);
 101                      continue;
 102                  }
 103                  
 104                  $right_id = false;
 105              }
 106  
 107              // Not enabled?
 108              if (!$row['module_enabled'])
 109              {
 110                  // If category is disabled then disable every child too
 111                  unset($this->module_cache['modules'][$key]);
 112                  $right_id = $row['right_id'];
 113                  continue;
 114              }
 115          }
 116  
 117          // Re-index (this is needed, else we are not able to array_slice later)
 118          $this->module_cache['modules'] = array_merge($this->module_cache['modules']);
 119  
 120          // Now build the module array, but exclude completely empty categories...
 121          $right_id = false;
 122          $names = array();
 123  
 124          foreach ($this->module_cache['modules'] as $key => $row)
 125          {
 126              // Skip branch
 127              if ($right_id !== false)
 128              {
 129                  if ($row['left_id'] < $right_id)
 130                  {
 131                      continue;
 132                  }
 133                  
 134                  $right_id = false;
 135              }
 136  
 137              // Category with no members on their way down (we have to check every level)
 138              if (!$row['module_basename'])
 139              {
 140                  $empty_category = true;
 141  
 142                  // We go through the branch and look for an activated module
 143                  foreach (array_slice($this->module_cache['modules'], $key + 1) as $temp_row)
 144                  {
 145                      if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id'])
 146                      {
 147                          // Module there
 148                          if ($temp_row['module_basename'] && $temp_row['module_enabled'])
 149                          {
 150                              $empty_category = false;
 151                              break;
 152                          }
 153                          continue;
 154                      }
 155                      break;
 156                  }
 157  
 158                  // Skip the branch
 159                  if ($empty_category)
 160                  {
 161                      $right_id = $row['right_id'];
 162                      continue;
 163                  }
 164              }
 165  
 166              $depth = sizeof($this->module_cache['parents'][$row['module_id']]);
 167  
 168              // We need to prefix the functions to not create a naming conflict
 169              
 170              // Function for building 'url_extra'
 171              $url_func = '_module_' . $row['module_basename'] . '_url';
 172  
 173              // Function for building the language name
 174              $lang_func = '_module_' . $row['module_basename'] . '_lang';
 175  
 176              // Custom function for calling parameters on module init (for example assigning template variables)
 177              $custom_func = '_module_' . $row['module_basename'];
 178  
 179              $names[$row['module_basename'] . '_' . $row['module_mode']][] = true;
 180              
 181              $module_row = array(
 182                  'depth'        => $depth,
 183  
 184                  'id'        => (int) $row['module_id'],
 185                  'parent'    => (int) $row['parent_id'],
 186                  'cat'        => ($row['right_id'] > $row['left_id'] + 1) ? true : false,
 187  
 188                  'is_duplicate'    => ($row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false,
 189  
 190                  'name'        => (string) $row['module_basename'],
 191                  'mode'        => (string) $row['module_mode'],
 192                  'display'    => (int) $row['module_display'],
 193  
 194                  'url_extra'    => (function_exists($url_func)) ? $url_func($row['module_mode']) : '',
 195                  
 196                  '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']),
 197                  'langname'    => $row['module_langname'],
 198  
 199                  'left'        => $row['left_id'],
 200                  'right'        => $row['right_id'],
 201              );
 202  
 203              if (function_exists($custom_func))
 204              {
 205                  $custom_func($row['module_mode'], $module_row);
 206              }
 207  
 208              $this->module_ary[] = $module_row;
 209          }
 210  
 211          unset($this->module_cache['modules'], $names);
 212      }
 213  
 214      /**
 215      * Check module authorisation
 216      * @todo Have a look at the eval statement and replace with other code...
 217      */
 218  	function module_auth($module_auth)
 219      {
 220          global $auth, $config;
 221          
 222          $module_auth = trim($module_auth);
 223  
 224          // Generally allowed to access module if module_auth is empty
 225          if (!$module_auth)
 226          {
 227              return true;
 228          }
 229  
 230          $is_auth = false;
 231          eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z_]+)#', '#cfg_([a-z_]+)#'), array('(int) $auth->acl_get("\\1"\\2)', '(int) $this->acl_forum_id', '(int) $auth->acl_getf_global("\\1")', '(int) $config["\\1"]'), $module_auth) . ');');
 232  
 233          return $is_auth;
 234      }
 235  
 236      /**
 237      * Set active module
 238      */
 239  	function set_active($id = false, $mode = false)
 240      {
 241          $icat = false;
 242          $this->active_module = false;
 243  
 244          if (request_var('icat', ''))
 245          {
 246              $icat = $id;
 247              $id = request_var('icat', '');
 248          }
 249  
 250          $category = false;
 251          foreach ($this->module_ary as $row_id => $item_ary)
 252          {
 253              // If this is a module and it's selected, active
 254              // If this is a category and the module is the first within it, active
 255              // If this is a module and no mode selected, select first mode
 256              // If no category or module selected, go active for first module in first category
 257              if (
 258                  (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) ||
 259                  ($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat && $item_ary['display']) ||
 260                  (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) ||
 261                  (!$id && !$mode && !$item_ary['cat'] && $item_ary['display'])
 262                  )
 263              {
 264                  if ($item_ary['cat'])
 265                  {
 266                      $id = $icat;
 267                      $icat = false;
 268  
 269                      continue;
 270                  }
 271  
 272                  $this->p_id        = $item_ary['id'];
 273                  $this->p_parent    = $item_ary['parent'];
 274                  $this->p_name    = $item_ary['name'];
 275                  $this->p_mode     = $item_ary['mode'];
 276                  $this->p_left    = $item_ary['left'];
 277                  $this->p_right    = $item_ary['right'];
 278  
 279                  $this->module_cache['parents'] = $this->module_cache['parents'][$this->p_id];
 280                  $this->active_module = $item_ary['id'];
 281  
 282                  break;
 283              }
 284              else if (($item_ary['cat'] && $item_ary['id'] === (int) $id) || ($item_ary['parent'] === $category && $item_ary['cat']))
 285              {
 286                  $category = $item_ary['id'];
 287              }
 288          }
 289      }
 290  
 291      /**
 292      * Loads currently active module
 293      *
 294      * This method loads a given module, passing it the relevant id and mode.
 295      */
 296  	function load_active($mode = false, $module_url = false, $execute_module = true)
 297      {
 298          global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user;
 299  
 300          $module_path = $phpbb_root_path . 'includes/' . $this->p_class;
 301          $icat = request_var('icat', '');
 302  
 303          if ($this->active_module === false)
 304          {
 305              trigger_error('Module not accessible', E_USER_ERROR);
 306          }
 307  
 308          if (!class_exists("{$this->p_class}_$this->p_name"))
 309          {
 310              if (!file_exists("$module_path/{$this->p_class}_$this->p_name.$phpEx"))
 311              {
 312                  trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR);
 313              }
 314  
 315              include("$module_path/{$this->p_class}_$this->p_name.$phpEx");
 316  
 317              if (!class_exists("{$this->p_class}_$this->p_name"))
 318              {
 319                  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);
 320              }
 321  
 322              if (!empty($mode))
 323              {
 324                  $this->p_mode = $mode;
 325              }
 326  
 327              // Create a new instance of the desired module ... if it has a
 328              // constructor it will of course be executed
 329              $instance = "{$this->p_class}_$this->p_name";
 330  
 331              $this->module = new $instance($this);
 332  
 333              // We pre-define the action parameter we are using all over the place
 334              if (defined('IN_ADMIN'))
 335              {
 336                  // Not being able to overwrite ;)
 337                  $this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$this->p_id}") . (($icat) ? '&amp;icat=' . $icat : '') . "&amp;mode={$this->p_mode}";
 338              }
 339              else
 340              {
 341                  // If user specified the module url we will use it...
 342                  if ($module_url !== false)
 343                  {
 344                      $this->module->u_action = $module_url;
 345                  }
 346                  else
 347                  {
 348                      $this->module->u_action = $phpbb_root_path . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name'];
 349                  }
 350  
 351                  $this->module->u_action = append_sid($this->module->u_action, "i={$this->p_id}") . (($icat) ? '&amp;icat=' . $icat : '') . "&amp;mode={$this->p_mode}";
 352              }
 353  
 354              // Assign the module path for re-usage
 355              $this->module->module_path = $module_path . '/';
 356  
 357              // Execute the main method for the new instance, we send the module id and mode as parameters
 358              // Users are able to call the main method after this function to be able to assign additional parameters manually
 359              if ($execute_module)
 360              {
 361                  $this->module->main(($this->p_name) ? $this->p_name : $this->p_id, $this->p_mode);
 362              }
 363  
 364              return;
 365          }
 366      }
 367  
 368      /**
 369      * Get parents
 370      */
 371  	function get_parents($parent_id, $left_id, $right_id, &$all_parents)
 372      {
 373          global $db;
 374  
 375          $parents = array();
 376  
 377          if ($parent_id > 0)
 378          {
 379              foreach ($all_parents as $module_id => $row)
 380              {
 381                  if ($row['left_id'] < $left_id && $row['right_id'] > $right_id)
 382                  {
 383                      $parents[$module_id] = $row['parent_id'];
 384                  }
 385  
 386                  if ($row['left_id'] > $left_id)
 387                  {
 388                      break;
 389                  }
 390              }
 391          }
 392  
 393          return $parents;
 394      }
 395  
 396      /**
 397      * Get tree branch
 398      */
 399  	function get_branch($left_id, $right_id, $remaining)
 400      {
 401          $branch = array();
 402  
 403          foreach ($remaining as $key => $row)
 404          {
 405              if ($row['left_id'] > $left_id && $row['left_id'] < $right_id)
 406              {
 407                  $branch[] = $row;
 408                  continue;
 409              }
 410              break;
 411          }
 412  
 413          return $branch;
 414      }
 415  
 416      /**
 417      * Build true binary tree from given array
 418      * Not in use
 419      */
 420  	function build_tree(&$modules, &$parents)
 421      {
 422          $tree = array();
 423  
 424          foreach ($modules as $row)
 425          {
 426              $branch = &$tree;
 427  
 428              if ($row['parent_id'])
 429              {
 430                  // Go through the tree to find our branch
 431                  $parent_tree = $parents[$row['module_id']];
 432  
 433                  foreach ($parent_tree as $id => $value)
 434                  {
 435                      if (!isset($branch[$id]) && isset($branch['child']))
 436                      {
 437                          $branch = &$branch['child'];
 438                      }
 439                      $branch = &$branch[$id];
 440                  }
 441                  $branch = &$branch['child'];
 442              }
 443  
 444              $branch[$row['module_id']] = $row;
 445              if (!isset($branch[$row['module_id']]['child']))
 446              {
 447                  $branch[$row['module_id']]['child'] = array();
 448              }
 449          }
 450  
 451          return $tree;
 452      }
 453  
 454      /**
 455      * Build navigation structure
 456      */
 457  	function assign_tpl_vars($module_url)
 458      {
 459          global $template;
 460  
 461          $current_id = $right_id = false;
 462  
 463          // Make sure the module_url has a question mark set, effectively determining the delimiter to use
 464          $delim = (strpos($module_url, '?') === false) ? '?' : '&amp;';
 465  
 466          $current_padding = $current_depth = 0;
 467          $linear_offset     = 'l_block1';
 468          $tabular_offset = 't_block2';
 469  
 470          // Generate the list of modules, we'll do this in two ways ...
 471          // 1) In a linear fashion
 472          // 2) In a combined tabbed + linear fashion ... tabs for the categories
 473          //    and a linear list for subcategories/items
 474          foreach ($this->module_ary as $row_id => $item_ary)
 475          {
 476              // Skip hidden modules
 477              if (!$item_ary['display'])
 478              {
 479                  continue;
 480              }
 481  
 482              // Skip branch
 483              if ($right_id !== false)
 484              {
 485                  if ($item_ary['left'] < $right_id)
 486                  {
 487                      continue;
 488                  }
 489  
 490                  $right_id = false;
 491              }
 492  
 493              // Category with no members on their way down (we have to check every level)
 494              if (!$item_ary['name'])
 495              {
 496                  $empty_category = true;
 497  
 498                  // We go through the branch and look for an activated module
 499                  foreach (array_slice($this->module_ary, $row_id + 1) as $temp_row)
 500                  {
 501                      if ($temp_row['left'] > $item_ary['left'] && $temp_row['left'] < $item_ary['right'])
 502                      {
 503                          // Module there and displayed?
 504                          if ($temp_row['name'] && $temp_row['display'])
 505                          {
 506                              $empty_category = false;
 507                              break;
 508                          }
 509                          continue;
 510                      }
 511                      break;
 512                  }
 513  
 514                  // Skip the branch
 515                  if ($empty_category)
 516                  {
 517                      $right_id = $item_ary['right'];
 518                      continue;
 519                  }
 520              }
 521  
 522              // Select first id we can get
 523              if (!$current_id && (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id))
 524              {
 525                  $current_id = $item_ary['id'];
 526              }
 527  
 528              $depth = $item_ary['depth'];
 529  
 530              if ($depth > $current_depth)
 531              {
 532                  $linear_offset = $linear_offset . '.l_block' . ($depth + 1);
 533                  $tabular_offset = ($depth + 1 > 2) ? $tabular_offset . '.t_block' . ($depth + 1) : $tabular_offset;
 534              }
 535              else if ($depth < $current_depth)
 536              {
 537                  for ($i = $current_depth - $depth; $i > 0; $i--)
 538                  {
 539                      $linear_offset = substr($linear_offset, 0, strrpos($linear_offset, '.'));
 540                      $tabular_offset = ($i + $depth > 1) ? substr($tabular_offset, 0, strrpos($tabular_offset, '.')) : $tabular_offset;
 541                  }
 542              }
 543  
 544              $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']);
 545              $u_title .= (!$item_ary['cat'] && isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : '';
 546  
 547              // Only output a categories items if it's currently selected
 548              if (!$depth || ($depth && (in_array($item_ary['parent'], array_values($this->module_cache['parents'])) || $item_ary['parent'] == $this->p_parent)))
 549              {
 550                  $use_tabular_offset = (!$depth) ? 't_block1' : $tabular_offset;
 551  
 552                  $tpl_ary = array(
 553                      'L_TITLE'        => $item_ary['lang'],
 554                      'S_SELECTED'    => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id) ? true : false,
 555                      'U_TITLE'        => $u_title
 556                  );
 557  
 558                  $template->assign_block_vars($use_tabular_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER)));
 559              }
 560  
 561              $tpl_ary = array(
 562                  'L_TITLE'        => $item_ary['lang'],
 563                  'S_SELECTED'    => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id) ? true : false,
 564                  'U_TITLE'        => $u_title
 565              );
 566  
 567              $template->assign_block_vars($linear_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER)));
 568  
 569              $current_depth = $depth;
 570          }
 571      }
 572  
 573      /**
 574      * Returns desired template name
 575      */
 576  	function get_tpl_name()
 577      {
 578          return $this->module->tpl_name . '.html';
 579      }
 580  
 581      /**
 582      * Returns the desired page title
 583      */
 584  	function get_page_title()
 585      {
 586          global $user;
 587  
 588          if (!isset($this->module->page_title))
 589          {
 590              return '';
 591          }
 592  
 593          return (isset($user->lang[$this->module->page_title])) ? $user->lang[$this->module->page_title] : $this->module->page_title;
 594      }
 595  
 596      /**
 597      * Load module as the current active one without the need for registering it
 598      */
 599  	function load($class, $name, $mode = false)
 600      {
 601          $this->p_class = $class;
 602          $this->p_name = $name;
 603  
 604          // Set active module to true instead of using the id
 605          $this->active_module = true;
 606  
 607          $this->load_active($mode);
 608      }
 609  
 610      /**
 611      * Display module
 612      */
 613  	function display($page_title, $display_online_list = true)
 614      {
 615          global $template, $user;
 616  
 617          // Generate the page
 618          if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
 619          {
 620              adm_page_header($page_title);
 621          }
 622          else
 623          {
 624              page_header($page_title, $display_online_list);
 625          }
 626  
 627          $template->set_filenames(array(
 628              'body' => $this->get_tpl_name())
 629          );
 630  
 631          if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
 632          {
 633              adm_page_footer();
 634          }
 635          else
 636          {
 637              page_footer();
 638          }
 639      }
 640  
 641      /**
 642      * Toggle whether this module will be displayed or not
 643      */
 644  	function set_display($id, $mode = false, $display = true)
 645      {
 646          foreach ($this->module_ary as $row_id => $item_ary)
 647          {
 648              if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode))
 649              {
 650                  $this->module_ary[$row_id]['display'] = (int) $display;
 651              }
 652          }
 653      }
 654  }
 655  
 656  ?>


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6