[ Index ] |
PHP Cross Reference of phpBB-3.1.12-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jan 11 00:25:41 2018 | Cross-referenced by PHPXref 0.7.1 |