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_manager.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 17.65 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\module;
 015   
 016  use phpbb\module\exception\module_exception;
 017  use phpbb\module\exception\module_not_found_exception;
 018   
 019  class module_manager
 020  {
 021      /**
 022       * @var \phpbb\cache\driver\driver_interface
 023       */
 024      protected $cache;
 025   
 026      /**
 027       * @var \phpbb\db\driver\driver_interface
 028       */
 029      protected $db;
 030   
 031      /**
 032       * @var \phpbb\extension\manager
 033       */
 034      protected $extension_manager;
 035   
 036      /**
 037       * @var string
 038       */
 039      protected $modules_table;
 040   
 041      /**
 042       * @var string
 043       */
 044      protected $phpbb_root_path;
 045   
 046      /**
 047       * @var string
 048       */
 049      protected $php_ext;
 050   
 051      /**
 052       * Constructor
 053       *
 054       * @param \phpbb\cache\driver\driver_interface    $cache                Cache driver
 055       * @param \phpbb\db\driver\driver_interface        $db                    Database driver
 056       * @param \phpbb\extension\manager                $ext_manager        Extension manager
 057       * @param string                                $modules_table        Module database table's name
 058       * @param string                                $phpbb_root_path    Path to phpBB's root
 059       * @param string                                $php_ext            Extension of PHP files
 060       */
 061      public function __construct(\phpbb\cache\driver\driver_interface $cache, \phpbb\db\driver\driver_interface $db, \phpbb\extension\manager $ext_manager, $modules_table, $phpbb_root_path, $php_ext)
 062      {
 063          $this->cache                = $cache;
 064          $this->db                    = $db;
 065          $this->extension_manager    = $ext_manager;
 066          $this->modules_table        = $modules_table;
 067          $this->phpbb_root_path        = $phpbb_root_path;
 068          $this->php_ext                = $php_ext;
 069      }
 070   
 071      /**
 072       * Get row for specified module
 073       *
 074       * @param int        $module_id        ID of the module
 075       * @param string    $module_class    Class of the module (acp, ucp, mcp etc...)
 076       *
 077       * @return array    Array of data fetched from the database
 078       *
 079       * @throws \phpbb\module\exception\module_not_found_exception    When there is no module with $module_id
 080       */
 081      public function get_module_row($module_id, $module_class)
 082      {
 083          $module_id = (int) $module_id;
 084   
 085          $sql = 'SELECT *
 086              FROM ' . $this->modules_table . "
 087              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 088                  AND module_id = $module_id";
 089          $result = $this->db->sql_query($sql);
 090          $row = $this->db->sql_fetchrow($result);
 091          $this->db->sql_freeresult($result);
 092   
 093          if (!$row)
 094          {
 095              throw new module_not_found_exception('NO_MODULE');
 096          }
 097   
 098          return $row;
 099      }
 100   
 101      /**
 102       * Get available module information from module files
 103       *
 104       * @param string    $module_class        Class of the module (acp, ucp, mcp etc...)
 105       * @param string    $module                ID of module
 106       * @param bool        $use_all_available    Use all available instead of just all
 107       *                                        enabled extensions
 108       *
 109       * @return array    Array with module information gathered from module info files.
 110       */
 111      public function get_module_infos($module_class, $module = '', $use_all_available = false)
 112      {
 113          $directory = $this->phpbb_root_path . 'includes/' . $module_class . '/info/';
 114          $fileinfo = array();
 115   
 116          $finder = $this->extension_manager->get_finder($use_all_available);
 117   
 118          $modules = $finder
 119              ->extension_suffix('_module')
 120              ->extension_directory("/$module_class")
 121              ->core_path("includes/$module_class/info/")
 122              ->core_prefix($module_class . '_')
 123              ->get_classes(true);
 124   
 125          foreach ($modules as $cur_module)
 126          {
 127              // Skip entries we do not need if we know the module we are
 128              // looking for
 129              if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module)
 130              {
 131                  continue;
 132              }
 133   
 134              $info_class = preg_replace('/_module$/', '_info', $cur_module);
 135   
 136              // If the class does not exist it might be following the old
 137              // format. phpbb_acp_info_acp_foo needs to be turned into
 138              // acp_foo_info and the respective file has to be included
 139              // manually because it does not support auto loading
 140              $old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module);
 141              $old_info_class = $old_info_class_file . '_info';
 142   
 143              if (class_exists($old_info_class))
 144              {
 145                  $info_class = $old_info_class;
 146              }
 147              else if (!class_exists($info_class))
 148              {
 149                  $info_class = $old_info_class;
 150   
 151                  // need to check class exists again because previous checks triggered autoloading
 152                  if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $this->php_ext))
 153                  {
 154                      include($directory . $old_info_class_file . '.' . $this->php_ext);
 155                  }
 156              }
 157   
 158              if (class_exists($info_class))
 159              {
 160                  $info = new $info_class();
 161                  $module_info = $info->module();
 162   
 163                  $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module;
 164   
 165                  $fileinfo[$main_class] = $module_info;
 166              }
 167          }
 168   
 169          ksort($fileinfo);
 170   
 171          return $fileinfo;
 172      }
 173   
 174      /**
 175       * Get module branch
 176       *
 177       * @param int        $module_id        ID of the module
 178       * @param string    $module_class    Class of the module (acp, ucp, mcp etc...)
 179       * @param string    $type            Type of branch (Expected values: all, parents or children)
 180       * @param bool        $include_module    Whether or not to include the specified module with $module_id
 181       *
 182       * @return array    Returns an array containing the modules in the specified branch type.
 183       */
 184      public function get_module_branch($module_id, $module_class, $type = 'all', $include_module = true)
 185      {
 186          $module_id = (int) $module_id;
 187   
 188          switch ($type)
 189          {
 190              case 'parents':
 191                  $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id';
 192              break;
 193   
 194              case 'children':
 195                  $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id';
 196              break;
 197   
 198              default:
 199                  $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id';
 200              break;
 201          }
 202   
 203          $rows = array();
 204   
 205          $sql = 'SELECT m2.*
 206              FROM ' . $this->modules_table . ' m1
 207              LEFT JOIN ' . $this->modules_table . " m2 ON ($condition)
 208              WHERE m1.module_class = '" . $this->db->sql_escape($module_class) . "'
 209                  AND m2.module_class = '" . $this->db->sql_escape($module_class) . "'
 210                  AND m1.module_id = $module_id
 211              ORDER BY m2.left_id DESC";
 212          $result = $this->db->sql_query($sql);
 213   
 214          while ($row = $this->db->sql_fetchrow($result))
 215          {
 216              if (!$include_module && $row['module_id'] == $module_id)
 217              {
 218                  continue;
 219              }
 220   
 221              $rows[] = $row;
 222          }
 223          $this->db->sql_freeresult($result);
 224   
 225          return $rows;
 226      }
 227   
 228      /**
 229       * Remove modules cache file
 230       *
 231       * @param string    $module_class    Class of the module (acp, ucp, mcp etc...)
 232       */
 233      public function remove_cache_file($module_class)
 234      {
 235          // Sanitise for future path use, it's escaped as appropriate for queries
 236          $cache_class = str_replace(array('.', '/', '\\'), '', basename($module_class));
 237          $this->cache->destroy('_modules_' . $cache_class);
 238          $this->cache->destroy('sql', $this->modules_table);
 239      }
 240   
 241      /**
 242       * Update/Add module
 243       *
 244       * @param array    &$module_data    The module data
 245       *
 246       * @throws \phpbb\module\exception\module_not_found_exception    When parent module or the category is not exist
 247       */
 248      public function update_module_data(&$module_data)
 249      {
 250          if (!isset($module_data['module_id']))
 251          {
 252              // no module_id means we're creating a new category/module
 253              if ($module_data['parent_id'])
 254              {
 255                  $sql = 'SELECT left_id, right_id
 256                      FROM ' . $this->modules_table . "
 257                      WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
 258                          AND module_id = " . (int) $module_data['parent_id'];
 259                  $result = $this->db->sql_query($sql);
 260                  $row = $this->db->sql_fetchrow($result);
 261                  $this->db->sql_freeresult($result);
 262   
 263                  if (!$row)
 264                  {
 265                      throw new module_not_found_exception('PARENT_NOT_EXIST');
 266                  }
 267   
 268                  // Workaround
 269                  $row['left_id'] = (int) $row['left_id'];
 270                  $row['right_id'] = (int) $row['right_id'];
 271   
 272                  $sql = 'UPDATE ' . $this->modules_table . "
 273                      SET left_id = left_id + 2, right_id = right_id + 2
 274                      WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
 275                          AND left_id > {$row['right_id']}";
 276                  $this->db->sql_query($sql);
 277   
 278                  $sql = 'UPDATE ' . $this->modules_table . "
 279                      SET right_id = right_id + 2
 280                      WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
 281                          AND {$row['left_id']} BETWEEN left_id AND right_id";
 282                  $this->db->sql_query($sql);
 283   
 284                  $module_data['left_id'] = (int) $row['right_id'];
 285                  $module_data['right_id'] = (int) $row['right_id'] + 1;
 286              }
 287              else
 288              {
 289                  $sql = 'SELECT MAX(right_id) AS right_id
 290                      FROM ' . $this->modules_table . "
 291                      WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'";
 292                  $result = $this->db->sql_query($sql);
 293                  $row = $this->db->sql_fetchrow($result);
 294                  $this->db->sql_freeresult($result);
 295   
 296                  $module_data['left_id'] = (int) $row['right_id'] + 1;
 297                  $module_data['right_id'] = (int) $row['right_id'] + 2;
 298              }
 299   
 300              $sql = 'INSERT INTO ' . $this->modules_table . ' ' . $this->db->sql_build_array('INSERT', $module_data);
 301              $this->db->sql_query($sql);
 302   
 303              $module_data['module_id'] = $this->db->sql_nextid();
 304          }
 305          else
 306          {
 307              $row = $this->get_module_row($module_data['module_id'], $module_data['module_class']);
 308   
 309              if ($module_data['module_basename'] && !$row['module_basename'])
 310              {
 311                  // we're turning a category into a module
 312                  $branch = $this->get_module_branch($module_data['module_id'], $module_data['module_class'], 'children', false);
 313   
 314                  if (sizeof($branch))
 315                  {
 316                      throw new module_not_found_exception('NO_CATEGORY_TO_MODULE');
 317                  }
 318              }
 319   
 320              if ($row['parent_id'] != $module_data['parent_id'])
 321              {
 322                  $this->move_module($module_data['module_id'], $module_data['parent_id'], $module_data['module_class']);
 323              }
 324   
 325              $update_ary = $module_data;
 326              unset($update_ary['module_id']);
 327   
 328              $sql = 'UPDATE ' . $this->modules_table . '
 329                  SET ' . $this->db->sql_build_array('UPDATE', $update_ary) . "
 330                  WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
 331                      AND module_id = " . (int) $module_data['module_id'];
 332              $this->db->sql_query($sql);
 333          }
 334      }
 335   
 336      /**
 337       * Move module around the tree
 338       *
 339       * @param int        $from_module_id    ID of the current parent module
 340       * @param int        $to_parent_id    ID of the target parent module
 341       * @param string    $module_class    Class of the module (acp, ucp, mcp etc...)
 342       *
 343       * @throws \phpbb\module\exception\module_not_found_exception    If the module specified to move modules from does not
 344       *                                                                 have any children.
 345       */
 346      public function move_module($from_module_id, $to_parent_id, $module_class)
 347      {
 348          $moved_modules = $this->get_module_branch($from_module_id, $module_class, 'children');
 349   
 350          if (empty($moved_modules))
 351          {
 352              throw new module_not_found_exception();
 353          }
 354   
 355          $from_data = $moved_modules[0];
 356          $diff = sizeof($moved_modules) * 2;
 357   
 358          $moved_ids = array();
 359          for ($i = 0, $size = sizeof($moved_modules); $i < $size; ++$i)
 360          {
 361              $moved_ids[] = $moved_modules[$i]['module_id'];
 362          }
 363   
 364          // Resync parents
 365          $sql = 'UPDATE ' . $this->modules_table . "
 366              SET right_id = right_id - $diff
 367              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 368                  AND left_id < " . (int) $from_data['right_id'] . '
 369                  AND right_id > ' . (int) $from_data['right_id'];
 370          $this->db->sql_query($sql);
 371   
 372          // Resync righthand side of tree
 373          $sql = 'UPDATE ' . $this->modules_table . "
 374              SET left_id = left_id - $diff, right_id = right_id - $diff
 375              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 376                  AND left_id > " . (int) $from_data['right_id'];
 377          $this->db->sql_query($sql);
 378   
 379          if ($to_parent_id > 0)
 380          {
 381              $to_data = $this->get_module_row($to_parent_id, $module_class);
 382   
 383              // Resync new parents
 384              $sql = 'UPDATE ' . $this->modules_table . "
 385                  SET right_id = right_id + $diff
 386                  WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 387                      AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id
 388                      AND ' . $this->db->sql_in_set('module_id', $moved_ids, true);
 389              $this->db->sql_query($sql);
 390   
 391              // Resync the righthand side of the tree
 392              $sql = 'UPDATE ' . $this->modules_table . "
 393                  SET left_id = left_id + $diff, right_id = right_id + $diff
 394                  WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 395                      AND left_id > " . (int) $to_data['right_id'] . '
 396                      AND ' . $this->db->sql_in_set('module_id', $moved_ids, true);
 397              $this->db->sql_query($sql);
 398   
 399              // Resync moved branch
 400              $to_data['right_id'] += $diff;
 401              if ($to_data['right_id'] > $from_data['right_id'])
 402              {
 403                  $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1);
 404              }
 405              else
 406              {
 407                  $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1);
 408              }
 409          }
 410          else
 411          {
 412              $sql = 'SELECT MAX(right_id) AS right_id
 413                  FROM ' . $this->modules_table . "
 414                  WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 415                      AND " . $this->db->sql_in_set('module_id', $moved_ids, true);
 416              $result = $this->db->sql_query($sql);
 417              $row = $this->db->sql_fetchrow($result);
 418              $this->db->sql_freeresult($result);
 419   
 420              $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1);
 421          }
 422   
 423          $sql = 'UPDATE ' . $this->modules_table . "
 424              SET left_id = left_id $diff, right_id = right_id $diff
 425              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 426                  AND " . $this->db->sql_in_set('module_id', $moved_ids);
 427          $this->db->sql_query($sql);
 428      }
 429   
 430      /**
 431       * Remove module from tree
 432       *
 433       * @param int        $module_id        ID of the module to delete
 434       * @param string    $module_class    Class of the module (acp, ucp, mcp etc...)
 435       *
 436       * @throws \phpbb\module\exception\module_exception    When the specified module cannot be removed
 437       */
 438      public function delete_module($module_id, $module_class)
 439      {
 440          $module_id = (int) $module_id;
 441   
 442          $row = $this->get_module_row($module_id, $module_class);
 443   
 444          $branch = $this->get_module_branch($module_id, $module_class, 'children', false);
 445   
 446          if (sizeof($branch))
 447          {
 448              throw new module_exception('CANNOT_REMOVE_MODULE');
 449          }
 450   
 451          // If not move
 452          $diff = 2;
 453          $sql = 'DELETE FROM ' . $this->modules_table . "
 454              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 455                  AND module_id = $module_id";
 456          $this->db->sql_query($sql);
 457   
 458          $row['right_id'] = (int) $row['right_id'];
 459          $row['left_id'] = (int) $row['left_id'];
 460   
 461          // Resync tree
 462          $sql = 'UPDATE ' . $this->modules_table . "
 463              SET right_id = right_id - $diff
 464              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 465                  AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}";
 466          $this->db->sql_query($sql);
 467   
 468          $sql = 'UPDATE ' . $this->modules_table . "
 469              SET left_id = left_id - $diff, right_id = right_id - $diff
 470              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 471                  AND left_id > {$row['right_id']}";
 472          $this->db->sql_query($sql);
 473      }
 474   
 475      /**
 476       * Move module position by $steps up/down
 477       *
 478       * @param array        $module_row        Array of module data
 479       * @param string    $module_class    Class of the module (acp, ucp, mcp etc...)
 480       * @param string    $action            Direction of moving (valid values: move_up or move_down)
 481       * @param int        $steps            Number of steps to move module
 482       *
 483       * @return string    Returns the language name of the module
 484       *
 485       * @throws \phpbb\module\exception\module_not_found_exception    When the specified module does not exists
 486       */
 487      public function move_module_by($module_row, $module_class, $action = 'move_up', $steps = 1)
 488      {
 489          /**
 490           * Fetch all the siblings between the module's current spot
 491           * and where we want to move it to. If there are less than $steps
 492           * siblings between the current spot and the target then the
 493           * module will move as far as possible
 494           */
 495          $sql = 'SELECT module_id, left_id, right_id, module_langname
 496              FROM ' . $this->modules_table . "
 497              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 498                  AND parent_id = " . (int) $module_row['parent_id'] . '
 499                  AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC');
 500          $result = $this->db->sql_query_limit($sql, $steps);
 501   
 502          $target = array();
 503          while ($row = $this->db->sql_fetchrow($result))
 504          {
 505              $target = $row;
 506          }
 507          $this->db->sql_freeresult($result);
 508   
 509          if (!sizeof($target))
 510          {
 511              // The module is already on top or bottom
 512              throw new module_not_found_exception();
 513          }
 514   
 515          /**
 516           * $left_id and $right_id define the scope of the nodes that are affected by the move.
 517           * $diff_up and $diff_down are the values to substract or add to each node's left_id
 518           * and right_id in order to move them up or down.
 519           * $move_up_left and $move_up_right define the scope of the nodes that are moving
 520           * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down.
 521           */
 522          if ($action == 'move_up')
 523          {
 524              $left_id = (int) $target['left_id'];
 525              $right_id = (int) $module_row['right_id'];
 526   
 527              $diff_up = (int) ($module_row['left_id'] - $target['left_id']);
 528              $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
 529   
 530              $move_up_left = (int) $module_row['left_id'];
 531              $move_up_right = (int) $module_row['right_id'];
 532          }
 533          else
 534          {
 535              $left_id = (int) $module_row['left_id'];
 536              $right_id = (int) $target['right_id'];
 537   
 538              $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
 539              $diff_down = (int) ($target['right_id'] - $module_row['right_id']);
 540   
 541              $move_up_left = (int) ($module_row['right_id'] + 1);
 542              $move_up_right = (int) $target['right_id'];
 543          }
 544   
 545          // Now do the dirty job
 546          $sql = 'UPDATE ' . $this->modules_table . "
 547              SET left_id = left_id + CASE
 548                  WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
 549                  ELSE {$diff_down}
 550              END,
 551              right_id = right_id + CASE
 552                  WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
 553                  ELSE {$diff_down}
 554              END
 555              WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
 556                  AND left_id BETWEEN {$left_id} AND {$right_id}
 557                  AND right_id BETWEEN {$left_id} AND {$right_id}";
 558          $this->db->sql_query($sql);
 559   
 560          $this->remove_cache_file($module_class);
 561   
 562          return $target['module_langname'];
 563      }
 564  }
 565