| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 # MantisBT - A PHP based bugtracking system 3 4 # MantisBT is free software: you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation, either version 2 of the License, or 7 # (at your option) any later version. 8 # 9 # MantisBT is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with MantisBT. If not, see <http://www.gnu.org/licenses/>. 16 17 18 /** 19 * Plugin API 20 * 21 * Handles the initialisation, management, and execution of plugins. 22 * 23 * @package CoreAPI 24 * @subpackage PluginAPI 25 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 26 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net 27 * @link http://www.mantisbt.org 28 * 29 * @uses access_api.php 30 * @uses config_api.php 31 * @uses constant_inc.php 32 * @uses database_api.php 33 * @uses error_api.php 34 * @uses event_api.php 35 * @uses helper_api.php 36 * @uses history_api.php 37 * @uses lang_api.php 38 */ 39 40 require_api( 'access_api.php' ); 41 require_api( 'config_api.php' ); 42 require_api( 'constant_inc.php' ); 43 require_api( 'database_api.php' ); 44 require_api( 'error_api.php' ); 45 require_api( 'event_api.php' ); 46 require_api( 'helper_api.php' ); 47 require_api( 'history_api.php' ); 48 require_api( 'lang_api.php' ); 49 50 # Cache variables ##### 51 52 $g_plugin_cache = array(); 53 $g_plugin_cache_priority = array(); 54 $g_plugin_cache_protected = array(); 55 $g_plugin_current = array(); 56 57 # Public API ##### 58 /** 59 * Get the currently executing plugin's basename. 60 * @return string Plugin basename, or null if no current plugin 61 */ 62 function plugin_get_current() { 63 global $g_plugin_current; 64 return( isset( $g_plugin_current[0] ) ? $g_plugin_current[0] : null ); 65 } 66 67 /** 68 * Add the current plugin to the stack 69 * @param string Plugin basename 70 */ 71 function plugin_push_current( $p_basename ) { 72 global $g_plugin_current; 73 array_unshift( $g_plugin_current, $p_basename ); 74 } 75 76 /** 77 * Remove the current plugin from the stack 78 * @return string Plugin basename, or null if no current plugin 79 */ 80 function plugin_pop_current() { 81 global $g_plugin_current; 82 return( isset( $g_plugin_current[0] ) ? array_shift( $g_plugin_current ) : null ); 83 } 84 85 /** 86 * Get the URL to the plugin wrapper page. 87 * @param string Page name 88 * @param string Plugin basename (defaults to current plugin) 89 */ 90 function plugin_page( $p_page, $p_redirect = false, $p_basename = null ) { 91 if( is_null( $p_basename ) ) { 92 $t_current = plugin_get_current(); 93 } else { 94 $t_current = $p_basename; 95 } 96 if( $p_redirect ) { 97 return 'plugin.php?page=' . $t_current . '/' . $p_page; 98 } else { 99 return helper_mantis_url( 'plugin.php?page=' . $t_current . '/' . $p_page ); 100 } 101 } 102 103 /** 104 * Return a path to a plugin file. 105 * @param string File name 106 * @param string Plugin basename 107 * @return mixed File path or false if FNF 108 */ 109 function plugin_file_path( $p_filename, $p_basename ) { 110 $t_file_path = config_get( 'plugin_path' ); 111 $t_file_path .= $p_basename . DIRECTORY_SEPARATOR; 112 $t_file_path .= 'files' . DIRECTORY_SEPARATOR . $p_filename; 113 114 return( is_file( $t_file_path ) ? $t_file_path : false ); 115 } 116 117 /** 118 * Get the URL to the plugin wrapper page. 119 * @param string Page name 120 * @param string Plugin basename (defaults to current plugin) 121 */ 122 function plugin_file( $p_file, $p_redirect = false, $p_basename = null ) { 123 if( is_null( $p_basename ) ) { 124 $t_current = plugin_get_current(); 125 } else { 126 $t_current = $p_basename; 127 } 128 if( $p_redirect ) { 129 return 'plugin_file.php?file=' . $t_current . '/' . $p_file; 130 } else { 131 return helper_mantis_url( 'plugin_file.php?file=' . $t_current . '/' . $p_file ); 132 } 133 } 134 135 /** 136 * Include the contents of a file as output. 137 * @param string File name 138 * @param string Plugin basename 139 */ 140 function plugin_file_include( $p_filename, $p_basename = null ) { 141 if( is_null( $p_basename ) ) { 142 $t_current = plugin_get_current(); 143 } else { 144 $t_current = $p_basename; 145 } 146 147 $t_file_path = plugin_file_path( $p_filename, $t_current ); 148 if( false === $t_file_path ) { 149 trigger_error( ERROR_GENERIC, ERROR ); 150 } 151 152 readfile( $t_file_path ); 153 } 154 155 /** 156 * Given a base table name for a plugin, add appropriate prefix and suffix. 157 * Convenience for plugin schema definitions. 158 * @param string Table name 159 * @param string Plugin basename (defaults to current plugin) 160 * @return string Full table name 161 */ 162 function plugin_table( $p_name, $p_basename = null ) { 163 if( is_null( $p_basename ) ) { 164 $t_current = plugin_get_current(); 165 } else { 166 $t_current = $p_basename; 167 } 168 return db_get_table( 'plugin_' . $t_current . '_' . $p_name ); 169 } 170 171 /** 172 * Get a plugin configuration option. 173 * @param string Configuration option name 174 * @param multi Default option value 175 */ 176 function plugin_config_get( $p_option, $p_default = null, $p_global = false ) { 177 $t_basename = plugin_get_current(); 178 $t_full_option = 'plugin_' . $t_basename . '_' . $p_option; 179 180 if( $p_global ) { 181 return config_get_global( $t_full_option, $p_default ); 182 } else { 183 return config_get( $t_full_option, $p_default ); 184 } 185 } 186 187 /** 188 * Set a plugin configuration option in the database. 189 * @param string Configuration option name 190 * @param multi Option value 191 * @param int User ID 192 * @param int Project ID 193 * @param int Access threshold 194 */ 195 function plugin_config_set( $p_option, $p_value, $p_user = NO_USER, $p_project = ALL_PROJECTS, $p_access = DEFAULT_ACCESS_LEVEL ) { 196 if( $p_access == DEFAULT_ACCESS_LEVEL ) { 197 $p_access = config_get_global( 'admin_site_threshold' ); 198 } 199 200 $t_basename = plugin_get_current(); 201 $t_full_option = 'plugin_' . $t_basename . '_' . $p_option; 202 203 config_set( $t_full_option, $p_value, $p_user, $p_project, $p_access ); 204 } 205 206 /** 207 * Delete a plugin configuration option from the database. 208 * @param string Configuration option name 209 * @param int User ID 210 * @param int Project ID 211 */ 212 function plugin_config_delete( $p_option, $p_user = ALL_USERS, $p_project = ALL_PROJECTS ) { 213 $t_basename = plugin_get_current(); 214 $t_full_option = 'plugin_' . $t_basename . '_' . $p_option; 215 216 config_delete( $t_full_option, $p_user, $p_project ); 217 } 218 219 /** 220 * Set plugin default values to global values without overriding anything. 221 * @param array Array of configuration option name/value pairs. 222 */ 223 function plugin_config_defaults( $p_options ) { 224 if( !is_array( $p_options ) ) { 225 return; 226 } 227 228 $t_basename = plugin_get_current(); 229 $t_option_base = 'plugin_' . $t_basename . '_'; 230 231 foreach( $p_options as $t_option => $t_value ) { 232 $t_full_option = $t_option_base . $t_option; 233 234 config_set_global( $t_full_option, $t_value, false ); 235 } 236 } 237 238 /** 239 * Get a language string for the plugin. 240 * Automatically prepends plugin_<basename> to the string requested. 241 * @param string Language string name 242 * @param string Plugin basename 243 * @return string Language string 244 */ 245 function plugin_lang_get( $p_name, $p_basename = null ) { 246 if( is_null( $p_basename ) ) { 247 $t_basename = plugin_get_current(); 248 } else { 249 $t_basename = $p_basename; 250 } 251 252 $t_name = 'plugin_' . $t_basename . '_' . $p_name; 253 254 return lang_get( $t_name ); 255 } 256 257 function plugin_history_log( $p_bug_id, $p_field_name, $p_old_value, $p_new_value = '', $p_user_id = null, $p_basename = null ) { 258 if( is_null( $p_basename ) ) { 259 $t_basename = plugin_get_current(); 260 } else { 261 $t_basename = $p_basename; 262 } 263 264 $t_field_name = $t_basename . '_' . $p_field_name; 265 266 history_log_event_direct( $p_bug_id, $t_field_name, $p_old_value, $p_new_value, $p_user_id, PLUGIN_HISTORY ); 267 } 268 269 /** 270 * Trigger a plugin-specific error with the given name and type. 271 * @param string Error name 272 * @param int Error type 273 * @param string Plugin basename 274 */ 275 function plugin_error( $p_error_name, $p_error_type = ERROR, $p_basename = null ) { 276 if( is_null( $p_basename ) ) { 277 $t_basename = plugin_get_current(); 278 } else { 279 $t_basename = $p_basename; 280 } 281 282 $t_error_code = "plugin_$t_basename}_$p_error_name}"; 283 284 trigger_error( $t_error_code, $p_error_type ); 285 286 return null; 287 } 288 289 /** 290 * Hook a plugin's callback function to an event. 291 * @param string Event name 292 * @param string Callback function 293 */ 294 function plugin_event_hook( $p_name, $p_callback ) { 295 $t_basename = plugin_get_current(); 296 event_hook( $p_name, $p_callback, $t_basename ); 297 } 298 299 /** 300 * Hook multiple plugin callbacks at once. 301 * @param array Array of event name/callback key/value pairs 302 */ 303 function plugin_event_hook_many( $p_hooks ) { 304 if( !is_array( $p_hooks ) ) { 305 return; 306 } 307 308 $t_basename = plugin_get_current(); 309 310 foreach( $p_hooks as $t_event => $t_callbacks ) { 311 if( !is_array( $t_callbacks ) ) { 312 event_hook( $t_event, $t_callbacks, $t_basename ); 313 continue; 314 } 315 316 foreach( $t_callbacks as $t_callback ) { 317 event_hook( $t_event, $t_callback, $t_basename ); 318 } 319 } 320 } 321 322 /** 323 * Allows a plugin to declare a 'child plugin' that 324 * can be loaded from the same parent directory. 325 * @param string Child plugin basename. 326 */ 327 function plugin_child( $p_child ) { 328 $t_basename = plugin_get_current(); 329 330 $t_plugin = plugin_register( $t_basename, false, $p_child ); 331 332 if( !is_null( $t_plugin ) ) { 333 plugin_init( $p_child ); 334 } 335 336 return $t_plugin; 337 } 338 339 # ## Plugin Management Helpers 340 341 /** 342 * Checks if a given plugin has been registered and initialized, 343 * and returns a boolean value representing the "loaded" state. 344 * @param string Plugin basename 345 * @return boolean Plugin loaded 346 */ 347 function plugin_is_loaded( $p_basename ) { 348 global $g_plugin_cache_init; 349 350 return ( isset( $g_plugin_cache_init[ $p_basename ] ) && $g_plugin_cache_init[ $p_basename ] ); 351 } 352 353 /** 354 * Converts a version string to an array, using some punctuation and 355 * number/lettor boundaries as splitting points. 356 * @param string Version string 357 * @return array Version array 358 */ 359 function plugin_version_array( $p_version ) { 360 $t_version = preg_replace( '/([a-zA-Z]+)([0-9]+)/', '\1.\2', $p_version ); 361 $t_version = preg_replace( '/([0-9]+)([a-zA-Z]+)/', '\1.\2', $t_version ); 362 363 $t_search = array( 364 ',', 365 '-', 366 '_', 367 ); 368 369 $t_replace = array( 370 '.', 371 '.', 372 '.', 373 ); 374 375 $t_version = explode( '.', str_replace( $t_search, $t_replace, $t_version ) ); 376 377 return $t_version; 378 } 379 380 /** 381 * Checks two version arrays sequentially for minimum or maximum version dependencies. 382 * @param array Version array to check 383 * @param array Version array required 384 * @param boolean Minimum (false) or maximum (true) version check 385 * @return int 1 if the version dependency succeeds, -1 if it fails 386 */ 387 function plugin_version_check( $p_version1, $p_version2, $p_maximum = false ) { 388 while( count( $p_version1 ) > 0 && count( $p_version2 ) > 0 ) { 389 390 # Grab the next version bits 391 $t_version1 = array_shift( $p_version1 ); 392 $t_version2 = array_shift( $p_version2 ); 393 394 # Convert to integers if possible 395 if( is_numeric( $t_version1 ) ) { 396 $t_version1 = (int) $t_version1; 397 } 398 if( is_numeric( $t_version2 ) ) { 399 $t_version2 = (int) $t_version2; 400 } 401 402 # Check for immediate version differences 403 if( $p_maximum ) { 404 if( $t_version1 < $t_version2 ) { 405 return 1; 406 } 407 else if( $t_version1 > $t_version2 ) { 408 return -1; 409 } 410 } else { 411 if( $t_version1 > $t_version2 ) { 412 return 1; 413 } 414 else if( $t_version1 < $t_version2 ) { 415 return -1; 416 } 417 } 418 } 419 420 # Versions matched exactly 421 if ( count( $p_version1 ) == 0 && count( $p_version2 ) == 0 ) { 422 return 1; 423 } 424 425 # Handle unmatched version bits 426 if( $p_maximum ) { 427 if ( count( $p_version2 ) > 0 ) { 428 return 1; 429 } 430 } else { 431 if ( count( $p_version1 ) > 0 ) { 432 return 1; 433 } 434 } 435 436 # No more comparisons 437 return -1; 438 } 439 440 /** 441 * Check a plugin dependency given a basename and required version. 442 * Versions are checked using PHP's library version_compare routine 443 * and allows both minimum and maximum version requirements. 444 * Returns 1 if plugin dependency is met, 0 if dependency not met, 445 * or -1 if dependency is the wrong version. 446 * @param string Plugin basename 447 * @param string Required version 448 * @return integer Plugin dependency status 449 */ 450 function plugin_dependency( $p_basename, $p_required, $p_initialized = false ) { 451 global $g_plugin_cache, $g_plugin_cache_init; 452 453 # check for registered dependency 454 if( isset( $g_plugin_cache[$p_basename] ) ) { 455 456 # require dependency initialized? 457 if( $p_initialized && !isset( $g_plugin_cache_init[$p_basename] ) ) { 458 return 0; 459 } 460 461 $t_required_array = explode( ',', $p_required ); 462 463 foreach( $t_required_array as $t_required ) { 464 $t_required = trim( $t_required ); 465 $t_maximum = false; 466 467 # check for a less-than-or-equal version requirement 468 $t_ltpos = strpos( $t_required, '<=' ); 469 if( $t_ltpos !== false ) { 470 $t_required = trim( utf8_substr( $t_required, $t_ltpos + 2 ) ); 471 $t_maximum = true; 472 } else { 473 $t_ltpos = strpos( $t_required, '<' ); 474 if( $t_ltpos !== false ) { 475 $t_required = trim( utf8_substr( $t_required, $t_ltpos + 1 ) ); 476 $t_maximum = true; 477 } 478 } 479 480 $t_version1 = plugin_version_array( $g_plugin_cache[$p_basename]->version ); 481 $t_version2 = plugin_version_array( $t_required ); 482 483 $t_check = plugin_version_check( $t_version1, $t_version2, $t_maximum ); 484 485 if ( $t_check < 1 ) { 486 return $t_check; 487 } 488 } 489 490 return 1; 491 } else { 492 return 0; 493 } 494 } 495 496 /** 497 * Checks to see if a plugin is 'protected' from uninstall. 498 * @param string Plugin basename 499 * @return boolean True if plugin is protected 500 */ 501 function plugin_protected( $p_basename ) { 502 global $g_plugin_cache_protected; 503 504 # For pseudo-plugin MantisCore, return protected as 1. 505 if( $p_basename == 'MantisCore' ) { 506 return 1; 507 } 508 509 return $g_plugin_cache_protected[$p_basename]; 510 } 511 512 /** 513 * Gets a plugin's priority. 514 * @param string Plugin basename 515 * @return int Plugin priority 516 */ 517 function plugin_priority( $p_basename ) { 518 global $g_plugin_cache_priority; 519 520 # For pseudo-plugin MantisCore, return priority as 3. 521 if( $p_basename == 'MantisCore' ) { 522 return 3; 523 } 524 525 return $g_plugin_cache_priority[$p_basename]; 526 } 527 528 # ## Plugin management functions 529 /** 530 * Determine if a given plugin is installed. 531 * @param string Plugin basename 532 * @return boolean True if plugin is installed 533 */ 534 function plugin_is_installed( $p_basename ) { 535 $t_plugin_table = db_get_table( 'plugin' ); 536 537 $t_forced_plugins = config_get_global( 'plugins_force_installed' ); 538 foreach( $t_forced_plugins as $t_basename => $t_priority ) { 539 if ( $t_basename == $p_basename ) { 540 return true; 541 } 542 } 543 544 $t_query = "SELECT COUNT(*) FROM $t_plugin_table WHERE basename=" . db_param(); 545 $t_result = db_query_bound( $t_query, array( $p_basename ) ); 546 return( 0 < db_result( $t_result ) ); 547 } 548 549 /** 550 * Install a plugin to the database. 551 * @param string Plugin basename 552 */ 553 function plugin_install( $p_plugin ) { 554 access_ensure_global_level( config_get_global( 'manage_plugin_threshold' ) ); 555 556 if( plugin_is_installed( $p_plugin->basename ) ) { 557 trigger_error( ERROR_PLUGIN_ALREADY_INSTALLED, WARNING ); 558 return null; 559 } 560 561 plugin_push_current( $p_plugin->basename ); 562 563 if( !$p_plugin->install() ) { 564 plugin_pop_current( $p_plugin->basename ); 565 return null; 566 } 567 568 $t_plugin_table = db_get_table( 'plugin' ); 569 570 $t_query = "INSERT INTO $t_plugin_table ( basename, enabled ) 571 VALUES ( " . db_param() . ", '1' )"; 572 db_query_bound( $t_query, array( $p_plugin->basename ) ); 573 574 if( false === ( plugin_config_get( 'schema', false ) ) ) { 575 plugin_config_set( 'schema', -1 ); 576 } 577 578 plugin_upgrade( $p_plugin ); 579 580 plugin_pop_current(); 581 } 582 583 /** 584 * Determine if an installed plugin needs to upgrade its schema. 585 * @param string Plugin basename 586 * @return boolean True if plugin needs schema ugrades. 587 */ 588 function plugin_needs_upgrade( $p_plugin ) { 589 $t_plugin_schema = $p_plugin->schema(); 590 if( is_null( $t_plugin_schema ) ) { 591 return false; 592 } 593 594 $t_config_option = 'plugin_' . $p_plugin->basename . '_schema'; 595 $t_plugin_schema_version = config_get( $t_config_option, -1, ALL_USERS, ALL_PROJECTS ); 596 597 return( $t_plugin_schema_version < count( $t_plugin_schema ) - 1 ); 598 } 599 600 /** 601 * Upgrade an installed plugin's schema. 602 * @param string Plugin basename 603 * @return multi True if upgrade completed, null if problem 604 */ 605 function plugin_upgrade( $p_plugin ) { 606 access_ensure_global_level( config_get_global( 'manage_plugin_threshold' ) ); 607 608 if( !plugin_is_installed( $p_plugin->basename ) ) { 609 return; 610 } 611 612 require_api( 'install_helper_functions_api.php' ); 613 614 plugin_push_current( $p_plugin->basename ); 615 616 $t_schema_version = plugin_config_get( 'schema', -1 ); 617 $t_schema = $p_plugin->schema(); 618 619 global $g_db; 620 $t_dict = NewDataDictionary( $g_db ); 621 622 $i = $t_schema_version + 1; 623 while( $i < count( $t_schema ) ) { 624 if( !$p_plugin->upgrade( $i ) ) { 625 plugin_pop_current(); 626 return false; 627 } 628 629 $t_target = $t_schema[$i][1][0]; 630 631 if( $t_schema[$i][0] == 'InsertData' ) { 632 $t_sqlarray = array( 633 'INSERT INTO ' . $t_schema[$i][1][0] . $t_schema[$i][1][1], 634 ); 635 } else if( $t_schema[$i][0] == 'UpdateSQL' ) { 636 $t_sqlarray = array( 637 'UPDATE ' . $t_schema[$i][1][0] . $t_schema[$i][1][1], 638 ); 639 $t_target = $t_schema[$i][1]; 640 } else if( $t_schema[$i][0] == 'UpdateFunction' ) { 641 $t_sqlarray = false; 642 if( isset( $t_schema[$i][2] ) ) { 643 $t_status = call_user_func( 'install_' . $t_schema[$i][1], $t_schema[$i][2] ); 644 } else { 645 $t_status = call_user_func( 'install_' . $t_schema[$i][1] ); 646 } 647 } else { 648 $t_sqlarray = call_user_func_array( Array( $t_dict, $t_schema[$i][0] ), $t_schema[$i][1] ); 649 } 650 651 if( $t_sqlarray ) { 652 $t_status = $t_dict->ExecuteSQLArray( $t_sqlarray ); 653 } 654 655 if( 2 == $t_status ) { 656 plugin_config_set( 'schema', $i ); 657 } else { 658 error_parameters( $i ); 659 trigger_error( ERROR_PLUGIN_UPGRADE_FAILED, ERROR ); 660 return null; 661 } 662 663 $i++; 664 } 665 666 plugin_pop_current(); 667 668 return true; 669 } 670 671 /** 672 * Uninstall a plugin from the database. 673 * @param string Plugin basename 674 */ 675 function plugin_uninstall( $p_plugin ) { 676 access_ensure_global_level( config_get_global( 'manage_plugin_threshold' ) ); 677 678 if( !plugin_is_installed( $p_plugin->basename ) || plugin_protected( $p_plugin->basename ) ) { 679 return; 680 } 681 682 $t_plugin_table = db_get_table( 'plugin' ); 683 684 $t_query = "DELETE FROM $t_plugin_table WHERE basename=" . db_param(); 685 db_query_bound( $t_query, array( $p_plugin->basename ) ); 686 687 plugin_push_current( $p_plugin->basename ); 688 689 $p_plugin->uninstall(); 690 691 plugin_pop_current(); 692 } 693 694 # ## Core usage only. 695 /** 696 * Search the plugins directory for plugins. 697 * @return array Plugin basename/info key/value pairs. 698 */ 699 function plugin_find_all() { 700 $t_plugin_path = config_get_global( 'plugin_path' ); 701 $t_plugins = array( 702 'MantisCore' => new MantisCorePlugin( 'MantisCore' ), 703 ); 704 705 if( $t_dir = opendir( $t_plugin_path ) ) { 706 while(( $t_file = readdir( $t_dir ) ) !== false ) { 707 if( '.' == $t_file || '..' == $t_file ) { 708 continue; 709 } 710 if( is_dir( $t_plugin_path . $t_file ) ) { 711 $t_plugin = plugin_register( $t_file, true ); 712 713 if( !is_null( $t_plugin ) ) { 714 $t_plugins[$t_file] = $t_plugin; 715 } 716 } 717 } 718 closedir( $t_dir ); 719 } 720 return $t_plugins; 721 } 722 723 /** 724 * Load a plugin's core class file. 725 * @param string Plugin basename 726 */ 727 function plugin_include( $p_basename, $p_child = null ) { 728 $t_path = config_get_global( 'plugin_path' ) . $p_basename . DIRECTORY_SEPARATOR; 729 730 if( is_null( $p_child ) ) { 731 $t_plugin_file = $t_path . $p_basename . '.php'; 732 } else { 733 $t_plugin_file = $t_path . $p_child . '.php'; 734 } 735 $t_included = false; 736 if( is_file( $t_plugin_file ) ) { 737 include_once( $t_plugin_file ); 738 $t_included = true; 739 } 740 741 return $t_included; 742 } 743 744 /** 745 * Register a plugin with MantisBT. 746 * The plugin class must already be loaded before calling. 747 * @param string Plugin classname without 'Plugin' postfix 748 */ 749 function plugin_register( $p_basename, $p_return = false, $p_child = null ) { 750 global $g_plugin_cache; 751 752 $t_basename = is_null( $p_child ) ? $p_basename : $p_child; 753 if( !isset( $g_plugin_cache[$t_basename] ) ) { 754 if( is_null( $p_child ) ) { 755 $t_classname = $p_basename . 'Plugin'; 756 } else { 757 $t_classname = $p_child . 'Plugin'; 758 } 759 760 # Include the plugin script if the class is not already declared. 761 if( !class_exists( $t_classname ) ) { 762 if( !plugin_include( $p_basename, $p_child ) ) { 763 return null; 764 } 765 } 766 767 # Make sure the class exists and that it's of the right type. 768 if( class_exists( $t_classname ) && is_subclass_of( $t_classname, 'MantisPlugin' ) ) { 769 plugin_push_current( is_null( $p_child ) ? $p_basename : $p_child ); 770 771 $t_plugin = new $t_classname( is_null( $p_child ) ? $p_basename : $p_child ); 772 773 plugin_pop_current(); 774 775 # Final check on the class 776 if( is_null( $t_plugin->name ) || is_null( $t_plugin->version ) ) { 777 return null; 778 } 779 780 if( $p_return ) { 781 return $t_plugin; 782 } else { 783 $g_plugin_cache[$t_basename] = $t_plugin; 784 } 785 } 786 } 787 788 return $g_plugin_cache[$t_basename]; 789 } 790 791 /** 792 * Find and register all installed plugins. 793 */ 794 function plugin_register_installed() { 795 global $g_plugin_cache_priority, $g_plugin_cache_protected; 796 797 # register plugins specified in the site configuration 798 $t_forced_plugins = config_get_global( 'plugins_force_installed' ); 799 foreach( $t_forced_plugins as $t_basename => $t_priority ) { 800 plugin_register( $t_basename ); 801 $g_plugin_cache_priority[$t_basename] = $t_priority; 802 $g_plugin_cache_protected[$t_basename] = true; 803 } 804 805 # register plugins installed via the interface/database 806 $t_plugin_table = db_get_table( 'plugin' ); 807 808 $t_query = "SELECT basename, priority, protected FROM $t_plugin_table WHERE enabled=" . db_param() . ' ORDER BY priority DESC'; 809 $t_result = db_query_bound( $t_query, Array( 1 ) ); 810 811 while( $t_row = db_fetch_array( $t_result ) ) { 812 $t_basename = $t_row['basename']; 813 plugin_register( $t_basename ); 814 $g_plugin_cache_priority[$t_basename] = $t_row['priority']; 815 $g_plugin_cache_protected[$t_basename] = $t_row['protected']; 816 } 817 } 818 819 /** 820 * Initialize all installed plugins. 821 * Post-signals EVENT_PLUGIN_INIT. 822 */ 823 function plugin_init_installed() { 824 if( OFF == config_get_global( 'plugins_enabled' ) || !db_table_exists( db_get_table( 'plugin' ) ) ) { 825 return; 826 } 827 828 global $g_plugin_cache, $g_plugin_current, $g_plugin_cache_priority, $g_plugin_cache_protected, $g_plugin_cache_init; 829 $g_plugin_cache = array(); 830 $g_plugin_current = array(); 831 $g_plugin_cache_init = array(); 832 $g_plugin_cache_priority = array(); 833 $g_plugin_cache_protected = array(); 834 835 plugin_register( 'MantisCore' ); 836 plugin_register_installed(); 837 838 $t_plugins = array_keys( $g_plugin_cache ); 839 840 do { 841 $t_continue = false; 842 $t_plugins_retry = array(); 843 844 foreach( $t_plugins as $t_basename ) { 845 if( plugin_init( $t_basename ) ) { 846 $t_continue = true; 847 848 } else { 849 # Dependent plugin 850 $t_plugins_retry[] = $t_basename; 851 } 852 } 853 854 $t_plugins = $t_plugins_retry; 855 } 856 while( $t_continue ); 857 858 event_signal( 'EVENT_PLUGIN_INIT' ); 859 } 860 861 /** 862 * Initialize a single plugin. 863 * @param string Plugin basename 864 * @return boolean True if plugin initialized, false otherwise. 865 */ 866 function plugin_init( $p_basename ) { 867 global $g_plugin_cache, $g_plugin_cache_init; 868 869 # handle dependent plugins 870 if( isset( $g_plugin_cache[$p_basename] ) ) { 871 $t_plugin = $g_plugin_cache[$p_basename]; 872 873 # hard dependencies; return false if the dependency is not registered, 874 # does not meet the version requirement, or is not yet initialized. 875 if( is_array( $t_plugin->requires ) ) { 876 foreach( $t_plugin->requires as $t_required => $t_version ) { 877 if( plugin_dependency( $t_required, $t_version, true ) !== 1 ) { 878 return false; 879 } 880 } 881 } 882 883 # soft dependencies; only return false if the soft dependency is 884 # registered, but not yet initialized. 885 if( is_array( $t_plugin->uses ) ) { 886 foreach( $t_plugin->uses as $t_used => $t_version ) { 887 if ( isset( $g_plugin_cache[ $t_used ] ) && !isset( $g_plugin_cache_init[ $t_used ] ) ) { 888 return false; 889 } 890 } 891 } 892 893 # if plugin schema needs an upgrade, do not initialize 894 if ( plugin_needs_upgrade( $t_plugin ) ) { 895 return false; 896 } 897 898 plugin_push_current( $p_basename ); 899 900 # load plugin error strings 901 global $g_lang_strings; 902 $t_lang = lang_get_current(); 903 $t_plugin_errors = $t_plugin->errors(); 904 905 foreach( $t_plugin_errors as $t_error_name => $t_error_string ) { 906 $t_error_code = "plugin_$p_basename}_$t_error_name}"; 907 $g_lang_strings[$t_lang]['MANTIS_ERROR'][$t_error_code] = $t_error_string; 908 } 909 910 # finish initializing the plugin 911 $t_plugin->__init(); 912 $g_plugin_cache_init[$p_basename] = true; 913 914 plugin_pop_current(); 915 916 return true; 917 } else { 918 return false; 919 } 920 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |