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