Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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

module.php

Zuletzt modifiziert: 09.10.2024, 12:55 - Dateigröße: 15.93 KiB


 001  <?php
 002  /**
 003  *
 004  * This file is part of the phpBB Forum Software package.
 005  *
 006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
 007  * @license GNU General Public License, version 2 (GPL-2.0)
 008  *
 009  * For full copyright and license information, please see
 010  * the docs/CREDITS.txt file.
 011  *
 012  */
 013   
 014  namespace phpbb\db\migration\tool;
 015   
 016  use phpbb\module\exception\module_exception;
 017   
 018  /**
 019  * Migration module management tool
 020  */
 021  class module implements \phpbb\db\migration\tool\tool_interface
 022  {
 023      /** @var \phpbb\cache\service */
 024      protected $cache;
 025   
 026      /** @var \phpbb\db\driver\driver_interface */
 027      protected $db;
 028   
 029      /** @var \phpbb\user */
 030      protected $user;
 031   
 032      /** @var \phpbb\module\module_manager */
 033      protected $module_manager;
 034   
 035      /** @var string */
 036      protected $phpbb_root_path;
 037   
 038      /** @var string */
 039      protected $php_ext;
 040   
 041      /** @var string */
 042      protected $modules_table;
 043   
 044      /** @var array */
 045      protected $module_categories = array();
 046   
 047      /**
 048      * Constructor
 049      *
 050      * @param \phpbb\db\driver\driver_interface $db
 051      * @param \phpbb\cache\service $cache
 052      * @param \phpbb\user $user
 053      * @param \phpbb\module\module_manager    $module_manager
 054      * @param string $phpbb_root_path
 055      * @param string $php_ext
 056      * @param string $modules_table
 057      */
 058      public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, \phpbb\module\module_manager $module_manager, $phpbb_root_path, $php_ext, $modules_table)
 059      {
 060          $this->db = $db;
 061          $this->cache = $cache;
 062          $this->user = $user;
 063          $this->module_manager = $module_manager;
 064          $this->phpbb_root_path = $phpbb_root_path;
 065          $this->php_ext = $php_ext;
 066          $this->modules_table = $modules_table;
 067      }
 068   
 069      /**
 070      * {@inheritdoc}
 071      */
 072      public function get_name()
 073      {
 074          return 'module';
 075      }
 076   
 077      /**
 078      * Module Exists
 079      *
 080      * Check if a module exists
 081      *
 082      * @param string $class The module class(acp|mcp|ucp)
 083      * @param int|string|bool $parent The parent module_id|module_langname (0 for no parent).
 084      *        Use false to ignore the parent check and check class wide.
 085      * @param int|string $module The module_id|module_langname you would like to
 086      *         check for to see if it exists
 087      * @return bool true/false if module exists
 088      */
 089      public function exists($class, $parent, $module)
 090      {
 091          // the main root directory should return true
 092          if (!$module)
 093          {
 094              return true;
 095          }
 096   
 097          $parent_sql = '';
 098          if ($parent !== false)
 099          {
 100              $parent = $this->get_parent_module_id($parent, $module, false);
 101              if ($parent === false)
 102              {
 103                  return false;
 104              }
 105   
 106              $parent_sql = 'AND parent_id = ' . (int) $parent;
 107          }
 108   
 109          $sql = 'SELECT module_id
 110              FROM ' . $this->modules_table . "
 111              WHERE module_class = '" . $this->db->sql_escape($class) . "'
 112                  $parent_sql
 113                  AND " . ((is_numeric($module)) ? 'module_id = ' . (int) $module : "module_langname = '" . $this->db->sql_escape($module) . "'");
 114          $result = $this->db->sql_query($sql);
 115          $module_id = $this->db->sql_fetchfield('module_id');
 116          $this->db->sql_freeresult($result);
 117   
 118          if ($module_id)
 119          {
 120              return true;
 121          }
 122   
 123          return false;
 124      }
 125   
 126      /**
 127      * Module Add
 128      *
 129      * Add a new module
 130      *
 131      * @param string $class The module class(acp|mcp|ucp)
 132      * @param int|string $parent The parent module_id|module_langname (0 for no parent)
 133      * @param array $data an array of the data on the new \module.
 134      *     This can be setup in two different ways.
 135      *    1. The "manual" way.  For inserting a category or one at a time.
 136      *        It will be merged with the base array shown a bit below,
 137      *            but at the least requires 'module_langname' to be sent, and,
 138      *            if you want to create a module (instead of just a category) you must
 139      *            send module_basename and module_mode.
 140      *        array(
 141      *            'module_enabled'    => 1,
 142      *            'module_display'    => 1,
 143      *               'module_basename'    => '',
 144      *            'module_class'        => $class,
 145      *               'parent_id'            => (int) $parent,
 146      *            'module_langname'    => '',
 147      *               'module_mode'        => '',
 148      *               'module_auth'        => '',
 149      *        )
 150      *    2. The "automatic" way.  For inserting multiple at a time based on the
 151      *            specs in the info file for the module(s).  For this to work the
 152      *            modules must be correctly setup in the info file.
 153      *        An example follows (this would insert the settings, log, and flag
 154      *            modes from the includes/acp/info/acp_asacp.php file):
 155      *         array(
 156      *             'module_basename'    => 'asacp',
 157      *             'modes'                => array('settings', 'log', 'flag'),
 158      *         )
 159      *         Optionally you may not send 'modes' and it will insert all of the
 160      *             modules in that info file.
 161      *     path, specify that here
 162      * @return null
 163      * @throws \phpbb\db\migration\exception
 164      */
 165      public function add($class, $parent = 0, $data = array())
 166      {
 167          global $user, $phpbb_log;
 168   
 169          // allow sending the name as a string in $data to create a category
 170          if (!is_array($data))
 171          {
 172              $data = array('module_langname' => $data);
 173          }
 174   
 175          $parent = $data['parent_id'] = $this->get_parent_module_id($parent, $data);
 176   
 177          if (!isset($data['module_langname']))
 178          {
 179              // The "automatic" way
 180              $basename = (isset($data['module_basename'])) ? $data['module_basename'] : '';
 181              $module = $this->get_module_info($class, $basename);
 182   
 183              foreach ($module['modes'] as $mode => $module_info)
 184              {
 185                  if (!isset($data['modes']) || in_array($mode, $data['modes']))
 186                  {
 187                      $new_module = array(
 188                          'module_basename'    => $basename,
 189                          'module_langname'    => $module_info['title'],
 190                          'module_mode'        => $mode,
 191                          'module_auth'        => $module_info['auth'],
 192                          'module_display'    => (isset($module_info['display'])) ? $module_info['display'] : true,
 193                          'before'            => (isset($module_info['before'])) ? $module_info['before'] : false,
 194                          'after'                => (isset($module_info['after'])) ? $module_info['after'] : false,
 195                      );
 196   
 197                      // Run the "manual" way with the data we've collected.
 198                      $this->add($class, $parent, $new_module);
 199                  }
 200              }
 201   
 202              return;
 203          }
 204   
 205          // The "manual" way
 206          if (!$this->exists($class, false, $parent))
 207          {
 208              throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent);
 209          }
 210   
 211          if ($this->exists($class, $parent, $data['module_langname']))
 212          {
 213              throw new \phpbb\db\migration\exception('MODULE_EXISTS', $data['module_langname']);
 214          }
 215   
 216          $module_data = array(
 217              'module_enabled'    => (isset($data['module_enabled'])) ? $data['module_enabled'] : 1,
 218              'module_display'    => (isset($data['module_display'])) ? $data['module_display'] : 1,
 219              'module_basename'    => (isset($data['module_basename'])) ? $data['module_basename'] : '',
 220              'module_class'        => $class,
 221              'parent_id'            => (int) $parent,
 222              'module_langname'    => (isset($data['module_langname'])) ? $data['module_langname'] : '',
 223              'module_mode'        => (isset($data['module_mode'])) ? $data['module_mode'] : '',
 224              'module_auth'        => (isset($data['module_auth'])) ? $data['module_auth'] : '',
 225          );
 226   
 227          try
 228          {
 229              $this->module_manager->update_module_data($module_data);
 230   
 231              // Success
 232              $module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']);
 233              $phpbb_log->add('admin', (isset($user->data['user_id'])) ? $user->data['user_id'] : ANONYMOUS, $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name));
 234   
 235              // Move the module if requested above/below an existing one
 236              if (isset($data['before']) && $data['before'])
 237              {
 238                  $sql = 'SELECT left_id
 239                      FROM ' . $this->modules_table . "
 240                      WHERE module_class = '" . $this->db->sql_escape($class) . "'
 241                          AND parent_id = " . (int) $parent . "
 242                          AND module_langname = '" . $this->db->sql_escape($data['before']) . "'";
 243                  $this->db->sql_query($sql);
 244                  $to_left = (int) $this->db->sql_fetchfield('left_id');
 245   
 246                  $sql = 'UPDATE ' . $this->modules_table . "
 247                      SET left_id = left_id + 2, right_id = right_id + 2
 248                      WHERE module_class = '" . $this->db->sql_escape($class) . "'
 249                          AND left_id >= $to_left
 250                          AND left_id < {$module_data['left_id']}";
 251                  $this->db->sql_query($sql);
 252   
 253                  $sql = 'UPDATE ' . $this->modules_table . "
 254                      SET left_id = $to_left, right_id = " . ($to_left + 1) . "
 255                      WHERE module_class = '" . $this->db->sql_escape($class) . "'
 256                          AND module_id = {$module_data['module_id']}";
 257                  $this->db->sql_query($sql);
 258              }
 259              else if (isset($data['after']) && $data['after'])
 260              {
 261                  $sql = 'SELECT right_id
 262                      FROM ' . $this->modules_table . "
 263                      WHERE module_class = '" . $this->db->sql_escape($class) . "'
 264                          AND parent_id = " . (int) $parent . "
 265                          AND module_langname = '" . $this->db->sql_escape($data['after']) . "'";
 266                  $this->db->sql_query($sql);
 267                  $to_right = (int) $this->db->sql_fetchfield('right_id');
 268   
 269                  $sql = 'UPDATE ' . $this->modules_table . "
 270                      SET left_id = left_id + 2, right_id = right_id + 2
 271                      WHERE module_class = '" . $this->db->sql_escape($class) . "'
 272                          AND left_id >= $to_right
 273                          AND left_id < {$module_data['left_id']}";
 274                  $this->db->sql_query($sql);
 275   
 276                  $sql = 'UPDATE ' . $this->modules_table . '
 277                      SET left_id = ' . ($to_right + 1) . ', right_id = ' . ($to_right + 2) . "
 278                      WHERE module_class = '" . $this->db->sql_escape($class) . "'
 279                          AND module_id = {$module_data['module_id']}";
 280                  $this->db->sql_query($sql);
 281              }
 282          }
 283          catch (module_exception $e)
 284          {
 285              // Error
 286              throw new \phpbb\db\migration\exception('MODULE_ERROR', $e->getMessage());
 287          }
 288   
 289          // Clear the Modules Cache
 290          $this->cache->destroy("_modules_$class");
 291      }
 292   
 293      /**
 294      * Module Remove
 295      *
 296      * Remove a module
 297      *
 298      * @param string $class The module class(acp|mcp|ucp)
 299      * @param int|string|bool $parent The parent module_id|module_langname(0 for no parent).
 300      *     Use false to ignore the parent check and check class wide.
 301      * @param int|string $module The module id|module_langname
 302      *     specify that here
 303      * @return null
 304      * @throws \phpbb\db\migration\exception
 305      */
 306      public function remove($class, $parent = 0, $module = '')
 307      {
 308          // Imitation of module_add's "automatic" and "manual" method so the uninstaller works from the same set of instructions for umil_auto
 309          if (is_array($module))
 310          {
 311              if (isset($module['module_langname']))
 312              {
 313                  // Manual Method
 314                  return $this->remove($class, $parent, $module['module_langname']);
 315              }
 316   
 317              // Failed.
 318              if (!isset($module['module_basename']))
 319              {
 320                  throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST');
 321              }
 322   
 323              // Automatic method
 324              $basename = $module['module_basename'];
 325              $module_info = $this->get_module_info($class, $basename);
 326   
 327              foreach ($module_info['modes'] as $mode => $info)
 328              {
 329                  if (!isset($module['modes']) || in_array($mode, $module['modes']))
 330                  {
 331                      $this->remove($class, $parent, $info['title']);
 332                  }
 333              }
 334          }
 335          else
 336          {
 337              if (!$this->exists($class, $parent, $module))
 338              {
 339                  return;
 340              }
 341   
 342              $parent_sql = '';
 343              if ($parent !== false)
 344              {
 345                  $parent = $this->get_parent_module_id($parent, $module);
 346                  $parent_sql = 'AND parent_id = ' . (int) $parent;
 347              }
 348   
 349              $module_ids = array();
 350              if (!is_numeric($module))
 351              {
 352                  $sql = 'SELECT module_id
 353                      FROM ' . $this->modules_table . "
 354                      WHERE module_langname = '" . $this->db->sql_escape($module) . "'
 355                          AND module_class = '" . $this->db->sql_escape($class) . "'
 356                          $parent_sql";
 357                  $result = $this->db->sql_query($sql);
 358                  while ($module_id = $this->db->sql_fetchfield('module_id'))
 359                  {
 360                      $module_ids[] = (int) $module_id;
 361                  }
 362                  $this->db->sql_freeresult($result);
 363              }
 364              else
 365              {
 366                  $module_ids[] = (int) $module;
 367              }
 368   
 369              foreach ($module_ids as $module_id)
 370              {
 371                  $this->module_manager->delete_module($module_id, $class);
 372              }
 373   
 374              $this->cache->destroy("_modules_$class");
 375          }
 376      }
 377   
 378      /**
 379      * {@inheritdoc}
 380      */
 381      public function reverse()
 382      {
 383          $arguments = func_get_args();
 384          $original_call = array_shift($arguments);
 385   
 386          $call = false;
 387          switch ($original_call)
 388          {
 389              case 'add':
 390                  $call = 'remove';
 391              break;
 392   
 393              case 'remove':
 394                  $call = 'add';
 395              break;
 396   
 397              case 'reverse':
 398                  // Reversing a reverse is just the call itself
 399                  $call = array_shift($arguments);
 400              break;
 401          }
 402   
 403          if ($call)
 404          {
 405              return call_user_func_array(array(&$this, $call), $arguments);
 406          }
 407      }
 408   
 409      /**
 410      * Wrapper for \acp_modules::get_module_infos()
 411      *
 412      * @param string $class Module Class
 413      * @param string $basename Module Basename
 414      * @return array Module Information
 415      * @throws \phpbb\db\migration\exception
 416      */
 417      protected function get_module_info($class, $basename)
 418      {
 419          $module = $this->module_manager->get_module_infos($class, $basename, true);
 420   
 421          if (empty($module))
 422          {
 423              throw new \phpbb\db\migration\exception('MODULE_INFO_FILE_NOT_EXIST', $class, $basename);
 424          }
 425   
 426          return array_pop($module);
 427      }
 428   
 429      /**
 430      * Get the list of installed module categories
 431      *    key - module_id
 432      *    value - module_langname
 433      *
 434      * @return null
 435      */
 436      protected function get_categories_list()
 437      {
 438          // Select the top level categories
 439          // and 2nd level [sub]categories
 440          $sql = 'SELECT m2.module_id, m2.module_langname
 441              FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2
 442              WHERE m1.parent_id = 0
 443                  AND (m1.module_id = m2.module_id OR m2.parent_id = m1.module_id)
 444              ORDER BY m1.module_id, m2.module_id ASC";
 445   
 446          $result = $this->db->sql_query($sql);
 447          while ($row = $this->db->sql_fetchrow($result))
 448          {
 449              $this->module_categories[(int) $row['module_id']] = $row['module_langname'];
 450          }
 451          $this->db->sql_freeresult($result);
 452      }
 453   
 454      /**
 455      * Get parent module id
 456      *
 457      * @param string|int $parent_id The parent module_id|module_langname
 458      * @param int|string|array $data The module_id, module_langname for existance checking or module data array for adding
 459      * @param bool $throw_exception The flag indicating if exception should be thrown on error
 460      * @return mixed The int parent module_id or false
 461      * @throws \phpbb\db\migration\exception
 462      */
 463      public function get_parent_module_id($parent_id, $data = '', $throw_exception = true)
 464      {
 465          // Initialize exception object placeholder
 466          $exception = false;
 467   
 468          // Allow '' to be sent as 0
 469          $parent_id = $parent_id ?: 0;
 470   
 471          // If automatic adding is in action, convert array back to string to simplify things
 472          if (is_array($data) && sizeof($data) == 1)
 473          {
 474              $data = $data['module_langname'];
 475          }
 476   
 477          if (!is_numeric($parent_id))
 478          {
 479              // Refresh the $module_categories array
 480              $this->get_categories_list();
 481   
 482              // Search for the parent module_langname
 483              $ids = array_keys($this->module_categories, $parent_id);
 484   
 485              switch (sizeof($ids))
 486              {
 487                  // No parent with the given module_langname exist
 488                  case 0:
 489                      $exception = new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent_id);
 490                  break;
 491   
 492                  // Return the module id
 493                  case 1:
 494                      $parent_id = (int) $ids[0];
 495                  break;
 496   
 497                  // Several modules with the given module_langname were found
 498                  // Try to determine the parent_id by the neighbour module parent
 499                  default:
 500                      if (is_array($data) && (isset($data['before']) || isset($data['after'])))
 501                      {
 502                          $neighbour_module_langname = isset($data['before']) ? $data['before'] : $data['after'];
 503                          $sql = 'SELECT parent_id
 504                              FROM ' . $this->modules_table . "
 505                              WHERE module_langname = '" . $this->db->sql_escape($neighbour_module_langname) . "'
 506                                  AND " . $this->db->sql_in_set('parent_id', $ids);
 507                          $result = $this->db->sql_query($sql);
 508                          $parent_id = (int) $this->db->sql_fetchfield('parent_id');
 509                          if (!$parent_id)
 510                          {
 511                              $exception = new \phpbb\db\migration\exception('PARENT_MODULE_FIND_ERROR', $data['parent_id']);
 512                          }
 513                      }
 514                      else if (!empty($data) && !is_array($data))
 515                      {
 516                          // The module_langname is set, checking for the module existance
 517                          // As more than 1 parents were found already, there's no way for null parent_id here
 518                          $sql = 'SELECT m2.module_id as module_parent_id
 519                              FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2
 520                              WHERE " . ((is_numeric($data)) ? 'm1.module_id = ' . (int) $data : "m1.module_langname = '" . $this->db->sql_escape($data)) . "'
 521                                  AND m2.module_id = m1.parent_id
 522                                  AND " . $this->db->sql_in_set('m2.module_id', $ids);
 523                          $result = $this->db->sql_query($sql);
 524                          $parent_id = (int) $this->db->sql_fetchfield('module_parent_id');
 525                      }
 526                      else
 527                      {
 528                          //Unable to get the parent module id, throwing an exception
 529                          $exception = new \phpbb\db\migration\exception('MODULE_EXIST_MULTIPLE', $parent_id);
 530                      }
 531                  break;
 532              }
 533          }
 534   
 535          if ($exception !== false)
 536          {
 537              if ($throw_exception)
 538              {
 539                  throw $exception;
 540              }
 541              return false;
 542          }
 543   
 544          return $parent_id;
 545      }
 546  }
 547