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