Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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

manager.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 16.01 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\extension;
015   
016  use Symfony\Component\DependencyInjection\ContainerInterface;
017   
018  /**
019  * The extension manager provides means to activate/deactivate extensions.
020  */
021  class manager
022  {
023      /** @var ContainerInterface */
024      protected $container;
025   
026      protected $db;
027      protected $config;
028      protected $cache;
029      protected $user;
030      protected $php_ext;
031      protected $extensions;
032      protected $extension_table;
033      protected $phpbb_root_path;
034      protected $cache_name;
035   
036      /**
037      * Creates a manager and loads information from database
038      *
039      * @param ContainerInterface $container A container
040      * @param \phpbb\db\driver\driver_interface $db A database connection
041      * @param \phpbb\config\config $config Config object
042      * @param \phpbb\filesystem $filesystem
043      * @param \phpbb\user $user User object
044      * @param string $extension_table The name of the table holding extensions
045      * @param string $phpbb_root_path Path to the phpbb includes directory.
046      * @param string $php_ext php file extension, defaults to php
047      * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null
048      * @param string $cache_name The name of the cache variable, defaults to _ext
049      */
050      public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem $filesystem, \phpbb\user $user, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext')
051      {
052          $this->cache = $cache;
053          $this->cache_name = $cache_name;
054          $this->config = $config;
055          $this->container = $container;
056          $this->db = $db;
057          $this->extension_table = $extension_table;
058          $this->filesystem = $filesystem;
059          $this->phpbb_root_path = $phpbb_root_path;
060          $this->php_ext = $php_ext;
061          $this->user = $user;
062   
063          $this->extensions = ($this->cache) ? $this->cache->get($this->cache_name) : false;
064   
065          if ($this->extensions === false)
066          {
067              $this->load_extensions();
068          }
069      }
070   
071      /**
072      * Loads all extension information from the database
073      *
074      * @return null
075      */
076      public function load_extensions()
077      {
078          $this->extensions = array();
079   
080          // Do not try to load any extensions if the extension table
081          // does not exist or when installing or updating.
082          // Note: database updater invokes this code, and in 3.0
083          // there is no extension table therefore the rest of this function
084          // fails
085          if (defined('IN_INSTALL') || version_compare($this->config['version'], '3.1.0-dev', '<'))
086          {
087              return;
088          }
089   
090          $sql = 'SELECT *
091              FROM ' . $this->extension_table;
092   
093          $result = $this->db->sql_query($sql);
094          $extensions = $this->db->sql_fetchrowset($result);
095          $this->db->sql_freeresult($result);
096   
097          foreach ($extensions as $extension)
098          {
099              $extension['ext_path'] = $this->get_extension_path($extension['ext_name']);
100              $this->extensions[$extension['ext_name']] = $extension;
101          }
102   
103          ksort($this->extensions);
104   
105          if ($this->cache)
106          {
107              $this->cache->put($this->cache_name, $this->extensions);
108          }
109      }
110   
111      /**
112      * Generates the path to an extension
113      *
114      * @param string $name The name of the extension
115      * @param bool $phpbb_relative Whether the path should be relative to phpbb root
116      * @return string Path to an extension
117      */
118      public function get_extension_path($name, $phpbb_relative = false)
119      {
120          $name = str_replace('.', '', $name);
121   
122          return (($phpbb_relative) ? $this->phpbb_root_path : '') . 'ext/' . $name . '/';
123      }
124   
125      /**
126      * Instantiates the extension meta class for the extension with the given name
127      *
128      * @param string $name The extension name
129      * @return \phpbb\extension\extension_interface Instance of the extension meta class or
130      *                     \phpbb\extension\base if the class does not exist
131      */
132      public function get_extension($name)
133      {
134          $extension_class_name = str_replace('/', '\\', $name) . '\\ext';
135   
136          $migrator = $this->container->get('migrator');
137   
138          if (class_exists($extension_class_name))
139          {
140              return new $extension_class_name($this->container, $this->get_finder(), $migrator, $name, $this->get_extension_path($name, true));
141          }
142          else
143          {
144              return new \phpbb\extension\base($this->container, $this->get_finder(), $migrator, $name, $this->get_extension_path($name, true));
145          }
146      }
147   
148      /**
149      * Instantiates the metadata manager for the extension with the given name
150      *
151      * @param string $name The extension name
152      * @param \phpbb\template\template $template The template manager
153      * @return \phpbb\extension\metadata_manager Instance of the metadata manager
154      */
155      public function create_extension_metadata_manager($name, \phpbb\template\template $template)
156      {
157          return new \phpbb\extension\metadata_manager($name, $this->config, $this, $template, $this->user, $this->phpbb_root_path);
158      }
159   
160      /**
161      * Runs a step of the extension enabling process.
162      *
163      * Allows the exentension to enable in a long running script that works
164      * in multiple steps across requests. State is kept for the extension
165      * in the extensions table.
166      *
167      * @param    string    $name    The extension's name
168      * @return    bool            False if enabling is finished, true otherwise
169      */
170      public function enable_step($name)
171      {
172          // ignore extensions that are already enabled
173          if (isset($this->extensions[$name]) && $this->extensions[$name]['ext_active'])
174          {
175              return false;
176          }
177   
178          $old_state = (isset($this->extensions[$name]['ext_state'])) ? unserialize($this->extensions[$name]['ext_state']) : false;
179   
180          $extension = $this->get_extension($name);
181   
182          if (!$extension->is_enableable())
183          {
184              return false;
185          }
186   
187          $state = $extension->enable_step($old_state);
188   
189          $active = ($state === false);
190   
191          $extension_data = array(
192              'ext_name'        => $name,
193              'ext_active'    => $active,
194              'ext_state'        => serialize($state),
195          );
196   
197          $this->extensions[$name] = $extension_data;
198          $this->extensions[$name]['ext_path'] = $this->get_extension_path($extension_data['ext_name']);
199          ksort($this->extensions);
200   
201          $sql = 'SELECT COUNT(ext_name) as row_count
202              FROM ' . $this->extension_table . "
203              WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
204          $result = $this->db->sql_query($sql);
205          $count = $this->db->sql_fetchfield('row_count');
206          $this->db->sql_freeresult($result);
207   
208          if ($count)
209          {
210              $sql = 'UPDATE ' . $this->extension_table . '
211                  SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . "
212                  WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
213              $this->db->sql_query($sql);
214          }
215          else
216          {
217              $sql = 'INSERT INTO ' . $this->extension_table . '
218                  ' . $this->db->sql_build_array('INSERT', $extension_data);
219              $this->db->sql_query($sql);
220          }
221   
222          if ($this->cache)
223          {
224              $this->cache->purge();
225          }
226   
227          if ($active)
228          {
229              $this->config->increment('assets_version', 1);
230          }
231   
232          return !$active;
233      }
234   
235      /**
236      * Enables an extension
237      *
238      * This method completely enables an extension. But it could be long running
239      * so never call this in a script that has a max_execution time.
240      *
241      * @param string $name The extension's name
242      * @return null
243      */
244      public function enable($name)
245      {
246          // @codingStandardsIgnoreStart
247          while ($this->enable_step($name));
248          // @codingStandardsIgnoreEnd
249      }
250   
251      /**
252      * Disables an extension
253      *
254      * Calls the disable method on the extension's meta class to allow it to
255      * process the event.
256      *
257      * @param string $name The extension's name
258      * @return bool False if disabling is finished, true otherwise
259      */
260      public function disable_step($name)
261      {
262          // ignore extensions that are already disabled
263          if (!isset($this->extensions[$name]) || !$this->extensions[$name]['ext_active'])
264          {
265              return false;
266          }
267   
268          $old_state = unserialize($this->extensions[$name]['ext_state']);
269   
270          $extension = $this->get_extension($name);
271          $state = $extension->disable_step($old_state);
272   
273          // continue until the state is false
274          if ($state !== false)
275          {
276              $extension_data = array(
277                  'ext_state'        => serialize($state),
278              );
279              $this->extensions[$name]['ext_state'] = serialize($state);
280   
281              $sql = 'UPDATE ' . $this->extension_table . '
282                  SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . "
283                  WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
284              $this->db->sql_query($sql);
285   
286              if ($this->cache)
287              {
288                  $this->cache->purge();
289              }
290   
291              return true;
292          }
293   
294          $extension_data = array(
295              'ext_active'    => false,
296              'ext_state'        => serialize(false),
297          );
298          $this->extensions[$name]['ext_active'] = false;
299          $this->extensions[$name]['ext_state'] = serialize(false);
300   
301          $sql = 'UPDATE ' . $this->extension_table . '
302              SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . "
303              WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
304          $this->db->sql_query($sql);
305   
306          if ($this->cache)
307          {
308              $this->cache->purge();
309          }
310   
311          return false;
312      }
313   
314      /**
315      * Disables an extension
316      *
317      * Disables an extension completely at once. This process could run for a
318      * while so never call this in a script that has a max_execution time.
319      *
320      * @param string $name The extension's name
321      * @return null
322      */
323      public function disable($name)
324      {
325          // @codingStandardsIgnoreStart
326          while ($this->disable_step($name));
327          // @codingStandardsIgnoreEnd
328      }
329   
330      /**
331      * Purge an extension
332      *
333      * Disables the extension first if active, and then calls purge on the
334      * extension's meta class to delete the extension's database content.
335      *
336      * @param string $name The extension's name
337      * @return bool False if purging is finished, true otherwise
338      */
339      public function purge_step($name)
340      {
341          // ignore extensions that do not exist
342          if (!isset($this->extensions[$name]))
343          {
344              return false;
345          }
346   
347          // disable first if necessary
348          if ($this->extensions[$name]['ext_active'])
349          {
350              $this->disable($name);
351          }
352   
353          $old_state = unserialize($this->extensions[$name]['ext_state']);
354   
355          $extension = $this->get_extension($name);
356          $state = $extension->purge_step($old_state);
357   
358          // continue until the state is false
359          if ($state !== false)
360          {
361              $extension_data = array(
362                  'ext_state'        => serialize($state),
363              );
364              $this->extensions[$name]['ext_state'] = serialize($state);
365   
366              $sql = 'UPDATE ' . $this->extension_table . '
367                  SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . "
368                  WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
369              $this->db->sql_query($sql);
370   
371              if ($this->cache)
372              {
373                  $this->cache->purge();
374              }
375   
376              return true;
377          }
378   
379          unset($this->extensions[$name]);
380   
381          $sql = 'DELETE FROM ' . $this->extension_table . "
382              WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
383          $this->db->sql_query($sql);
384   
385          if ($this->cache)
386          {
387              $this->cache->purge();
388          }
389   
390          return false;
391      }
392   
393      /**
394      * Purge an extension
395      *
396      * Purges an extension completely at once. This process could run for a while
397      * so never call this in a script that has a max_execution time.
398      *
399      * @param string $name The extension's name
400      * @return null
401      */
402      public function purge($name)
403      {
404          // @codingStandardsIgnoreStart
405          while ($this->purge_step($name));
406          // @codingStandardsIgnoreEnd
407      }
408   
409      /**
410      * Retrieves a list of all available extensions on the filesystem
411      *
412      * @return array An array with extension names as keys and paths to the
413      *               extension as values
414      */
415      public function all_available()
416      {
417          $available = array();
418          if (!is_dir($this->phpbb_root_path . 'ext/'))
419          {
420              return $available;
421          }
422   
423          $iterator = new \RecursiveIteratorIterator(
424              new \phpbb\recursive_dot_prefix_filter_iterator(
425                  new \RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/', \FilesystemIterator::NEW_CURRENT_AND_KEY | \FilesystemIterator::FOLLOW_SYMLINKS)
426              ),
427              \RecursiveIteratorIterator::SELF_FIRST
428          );
429          $iterator->setMaxDepth(2);
430   
431          foreach ($iterator as $file_info)
432          {
433              if ($file_info->isFile() && $file_info->getFilename() == 'composer.json')
434              {
435                  $ext_name = $iterator->getInnerIterator()->getSubPath();
436                  $composer_file = $iterator->getPath() . '/composer.json';
437   
438                  // Ignore the extension if there is no composer.json.
439                  if (!is_readable($composer_file) || !($ext_info = file_get_contents($composer_file)))
440                  {
441                      continue;
442                  }
443   
444                  $ext_info = json_decode($ext_info, true);
445                  $ext_name = str_replace(DIRECTORY_SEPARATOR, '/', $ext_name);
446   
447                  // Ignore the extension if directory depth is not correct or if the directory structure
448                  // does not match the name value specified in composer.json.
449                  if (substr_count($ext_name, '/') !== 1 || !isset($ext_info['name']) || $ext_name != $ext_info['name'])
450                  {
451                      continue;
452                  }
453   
454                  $available[$ext_name] = $this->phpbb_root_path . 'ext/' . $ext_name . '/';
455              }
456          }
457          ksort($available);
458          return $available;
459      }
460   
461      /**
462      * Retrieves all configured extensions.
463      *
464      * All enabled and disabled extensions are considered configured. A purged
465      * extension that is no longer in the database is not configured.
466      *
467      * @return array An array with extension names as keys and and the
468      *               database stored extension information as values
469      */
470      public function all_configured()
471      {
472          $configured = array();
473          foreach ($this->extensions as $name => $data)
474          {
475              $data['ext_path'] = $this->phpbb_root_path . $data['ext_path'];
476              $configured[$name] = $data;
477          }
478          return $configured;
479      }
480   
481      /**
482      * Retrieves all enabled extensions.
483      *
484      * @return array An array with extension names as keys and and the
485      *               database stored extension information as values
486      */
487      public function all_enabled()
488      {
489          $enabled = array();
490          foreach ($this->extensions as $name => $data)
491          {
492              if ($data['ext_active'])
493              {
494                  $enabled[$name] = $this->phpbb_root_path . $data['ext_path'];
495              }
496          }
497          return $enabled;
498      }
499   
500      /**
501      * Retrieves all disabled extensions.
502      *
503      * @return array An array with extension names as keys and and the
504      *               database stored extension information as values
505      */
506      public function all_disabled()
507      {
508          $disabled = array();
509          foreach ($this->extensions as $name => $data)
510          {
511              if (!$data['ext_active'])
512              {
513                  $disabled[$name] = $this->phpbb_root_path . $data['ext_path'];
514              }
515          }
516          return $disabled;
517      }
518   
519      /**
520      * Check to see if a given extension is available on the filesystem
521      *
522      * @param string $name Extension name to check NOTE: Can be user input
523      * @return bool Depending on whether or not the extension is available
524      */
525      public function is_available($name)
526      {
527          return file_exists($this->get_extension_path($name, true));
528      }
529   
530      /**
531      * Check to see if a given extension is enabled
532      *
533      * @param string $name Extension name to check
534      * @return bool Depending on whether or not the extension is enabled
535      */
536      public function is_enabled($name)
537      {
538          return isset($this->extensions[$name]) && $this->extensions[$name]['ext_active'];
539      }
540   
541      /**
542      * Check to see if a given extension is disabled
543      *
544      * @param string $name Extension name to check
545      * @return bool Depending on whether or not the extension is disabled
546      */
547      public function is_disabled($name)
548      {
549          return isset($this->extensions[$name]) && !$this->extensions[$name]['ext_active'];
550      }
551   
552      /**
553      * Check to see if a given extension is configured
554      *
555      * All enabled and disabled extensions are considered configured. A purged
556      * extension that is no longer in the database is not configured.
557      *
558      * @param string $name Extension name to check
559      * @return bool Depending on whether or not the extension is configured
560      */
561      public function is_configured($name)
562      {
563          return isset($this->extensions[$name]);
564      }
565   
566      /**
567      * Check to see if a given extension is purged
568      *
569      * An extension is purged if it is available, not enabled and not disabled.
570      *
571      * @param string $name Extension name to check
572      * @return bool Depending on whether or not the extension is purged
573      */
574      public function is_purged($name)
575      {
576          return $this->is_available($name) && !$this->is_configured($name);
577      }
578   
579      /**
580      * Instantiates a \phpbb\finder.
581      *
582      * @param bool $use_all_available Should we load all extensions, or just enabled ones
583      * @return \phpbb\finder An extension finder instance
584      */
585      public function get_finder($use_all_available = false)
586      {
587          $finder = new \phpbb\finder($this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
588          if ($use_all_available)
589          {
590              $finder->set_extensions(array_keys($this->all_available()));
591          }
592          else
593          {
594              $finder->set_extensions(array_keys($this->all_enabled()));
595          }
596          return $finder;
597      }
598  }
599