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