[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/phpbb/extension/ -> manager.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb\extension;
  15  
  16  use Symfony\Component\DependencyInjection\ContainerInterface;
  17  
  18  /**
  19  * The extension manager provides means to activate/deactivate extensions.
  20  */
  21  class manager
  22  {
  23      /** @var ContainerInterface */
  24      protected $container;
  25  
  26      protected $db;
  27      protected $config;
  28      protected $cache;
  29      protected $user;
  30      protected $php_ext;
  31      protected $extensions;
  32      protected $extension_table;
  33      protected $phpbb_root_path;
  34      protected $cache_name;
  35  
  36      /**
  37      * Creates a manager and loads information from database
  38      *
  39      * @param ContainerInterface $container A container
  40      * @param \phpbb\db\driver\driver_interface $db A database connection
  41      * @param \phpbb\config\config $config Config object
  42      * @param \phpbb\filesystem $filesystem
  43      * @param \phpbb\user $user User object
  44      * @param string $extension_table The name of the table holding extensions
  45      * @param string $phpbb_root_path Path to the phpbb includes directory.
  46      * @param string $php_ext php file extension, defaults to php
  47      * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null
  48      * @param string $cache_name The name of the cache variable, defaults to _ext
  49      */
  50  	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')
  51      {
  52          $this->cache = $cache;
  53          $this->cache_name = $cache_name;
  54          $this->config = $config;
  55          $this->container = $container;
  56          $this->db = $db;
  57          $this->extension_table = $extension_table;
  58          $this->filesystem = $filesystem;
  59          $this->phpbb_root_path = $phpbb_root_path;
  60          $this->php_ext = $php_ext;
  61          $this->user = $user;
  62  
  63          $this->extensions = ($this->cache) ? $this->cache->get($this->cache_name) : false;
  64  
  65          if ($this->extensions === false)
  66          {
  67              $this->load_extensions();
  68          }
  69      }
  70  
  71      /**
  72      * Loads all extension information from the database
  73      *
  74      * @return null
  75      */
  76  	public function load_extensions()
  77      {
  78          $this->extensions = array();
  79  
  80          // Do not try to load any extensions if the extension table
  81          // does not exist or when installing or updating.
  82          // Note: database updater invokes this code, and in 3.0
  83          // there is no extension table therefore the rest of this function
  84          // fails
  85          if (defined('IN_INSTALL') || version_compare($this->config['version'], '3.1.0-dev', '<'))
  86          {
  87              return;
  88          }
  89  
  90          $sql = 'SELECT *
  91              FROM ' . $this->extension_table;
  92  
  93          $result = $this->db->sql_query($sql);
  94          $extensions = $this->db->sql_fetchrowset($result);
  95          $this->db->sql_freeresult($result);
  96  
  97          foreach ($extensions as $extension)
  98          {
  99              $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 or null
 153      * @return \phpbb\extension\metadata_manager Instance of the metadata manager
 154      */
 155  	public function create_extension_metadata_manager($name, \phpbb\template\template $template = null)
 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                  $ext_name = str_replace(DIRECTORY_SEPARATOR, '/', $ext_name);
 437                  if ($this->is_available($ext_name))
 438                  {
 439                      $available[$ext_name] = $this->phpbb_root_path . 'ext/' . $ext_name . '/';
 440                  }
 441              }
 442          }
 443          ksort($available);
 444          return $available;
 445      }
 446  
 447      /**
 448      * Retrieves all configured extensions.
 449      *
 450      * All enabled and disabled extensions are considered configured. A purged
 451      * extension that is no longer in the database is not configured.
 452      *
 453      * @return array An array with extension names as keys and and the
 454      *               database stored extension information as values
 455      */
 456  	public function all_configured()
 457      {
 458          $configured = array();
 459          foreach ($this->extensions as $name => $data)
 460          {
 461              $data['ext_path'] = $this->phpbb_root_path . $data['ext_path'];
 462              $configured[$name] = $data;
 463          }
 464          return $configured;
 465      }
 466  
 467      /**
 468      * Retrieves all enabled extensions.
 469      *
 470      * @return array An array with extension names as keys and and the
 471      *               database stored extension information as values
 472      */
 473  	public function all_enabled()
 474      {
 475          $enabled = array();
 476          foreach ($this->extensions as $name => $data)
 477          {
 478              if ($data['ext_active'])
 479              {
 480                  $enabled[$name] = $this->phpbb_root_path . $data['ext_path'];
 481              }
 482          }
 483          return $enabled;
 484      }
 485  
 486      /**
 487      * Retrieves all disabled extensions.
 488      *
 489      * @return array An array with extension names as keys and and the
 490      *               database stored extension information as values
 491      */
 492  	public function all_disabled()
 493      {
 494          $disabled = array();
 495          foreach ($this->extensions as $name => $data)
 496          {
 497              if (!$data['ext_active'])
 498              {
 499                  $disabled[$name] = $this->phpbb_root_path . $data['ext_path'];
 500              }
 501          }
 502          return $disabled;
 503      }
 504  
 505      /**
 506      * Check to see if a given extension is available on the filesystem
 507      *
 508      * @param string $name Extension name to check NOTE: Can be user input
 509      * @return bool Depending on whether or not the extension is available
 510      */
 511  	public function is_available($name)
 512      {
 513          $md_manager = $this->create_extension_metadata_manager($name);
 514          try
 515          {
 516              return $md_manager->get_metadata('all') && $md_manager->validate_enable();
 517          }
 518          catch (\phpbb\extension\exception $e)
 519          {
 520              return false;
 521          }
 522      }
 523  
 524      /**
 525      * Check to see if a given extension is enabled
 526      *
 527      * @param string $name Extension name to check
 528      * @return bool Depending on whether or not the extension is enabled
 529      */
 530  	public function is_enabled($name)
 531      {
 532          return isset($this->extensions[$name]) && $this->extensions[$name]['ext_active'];
 533      }
 534  
 535      /**
 536      * Check to see if a given extension is disabled
 537      *
 538      * @param string $name Extension name to check
 539      * @return bool Depending on whether or not the extension is disabled
 540      */
 541  	public function is_disabled($name)
 542      {
 543          return isset($this->extensions[$name]) && !$this->extensions[$name]['ext_active'];
 544      }
 545  
 546      /**
 547      * Check to see if a given extension is configured
 548      *
 549      * All enabled and disabled extensions are considered configured. A purged
 550      * extension that is no longer in the database is not configured.
 551      *
 552      * @param string $name Extension name to check
 553      * @return bool Depending on whether or not the extension is configured
 554      */
 555  	public function is_configured($name)
 556      {
 557          return isset($this->extensions[$name]);
 558      }
 559  
 560      /**
 561      * Check to see if a given extension is purged
 562      *
 563      * An extension is purged if it is available, not enabled and not disabled.
 564      *
 565      * @param string $name Extension name to check
 566      * @return bool Depending on whether or not the extension is purged
 567      */
 568  	public function is_purged($name)
 569      {
 570          return $this->is_available($name) && !$this->is_configured($name);
 571      }
 572  
 573      /**
 574      * Instantiates a \phpbb\finder.
 575      *
 576      * @param bool $use_all_available Should we load all extensions, or just enabled ones
 577      * @return \phpbb\finder An extension finder instance
 578      */
 579  	public function get_finder($use_all_available = false)
 580      {
 581          $finder = new \phpbb\finder($this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
 582          if ($use_all_available)
 583          {
 584              $finder->set_extensions(array_keys($this->all_available()));
 585          }
 586          else
 587          {
 588              $finder->set_extensions(array_keys($this->all_enabled()));
 589          }
 590          return $finder;
 591      }
 592  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1