[ Index ] |
PHP Cross Reference of YOURLS |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * The filter/plugin API is located in this file, which allows for creating filters 5 * and hooking functions, and methods. The functions or methods will be run when 6 * the filter is called. 7 * 8 * Any of the syntaxes explained in the PHP documentation for the 9 * {@link https://www.php.net/manual/en/language.types.callable.php 'callback'} 10 * type are valid. 11 * 12 * This API is heavily inspired by the one I implemented in Zenphoto 1.3, which was heavily inspired by the one used in WordPress. 13 * 14 * @author Ozh 15 * @since 1.5 16 */ 17 18 /** 19 * This global var will collect filters with the following structure: 20 * $yourls_filters['hook']['array of priorities']['serialized function names']['array of ['array (functions, accepted_args, filter or action)]'] 21 * 22 * Real life example : 23 * print_r($yourls_filters) : 24 * Array 25 * ( 26 * [plugins_loaded] => Array 27 * ( 28 * [10] => Array 29 * ( 30 * [yourls_kses_init] => Array 31 * ( 32 * [function] => yourls_kses_init 33 * [accepted_args] => 1 34 * [type] => action 35 * ) 36 * [yourls_tzp_config] => Array 37 * ( 38 * [function] => yourls_tzp_config 39 * [accepted_args] => 1 40 * [type] => action 41 * ) 42 * ) 43 * ) 44 * [admin_menu] => Array 45 * ( 46 * [10] => Array 47 * ( 48 * [ozh_show_db] => Array 49 * ( 50 * [function] => ozh_show_db 51 * [accepted_args] => 52 * [type] => filter 53 * ) 54 * ) 55 * ) 56 * ) 57 * 58 * @var array $yourls_filters 59 */ 60 if ( !isset( $yourls_filters ) ) { 61 $yourls_filters = []; 62 } 63 64 /** 65 * This global var will collect 'done' actions with the following structure: 66 * $yourls_actions['hook'] => number of time this action was done 67 * 68 * @var array $yourls_actions 69 */ 70 if ( !isset( $yourls_actions ) ) { 71 $yourls_actions = []; 72 } 73 74 /** 75 * Registers a filtering function 76 * 77 * Typical use: 78 * yourls_add_filter('some_hook', 'function_handler_for_hook'); 79 * 80 * @link https://docs.yourls.org/development/plugins.html 81 * @param string $hook the name of the YOURLS element to be filtered or YOURLS action to be triggered 82 * @param callable $function_name the name of the function that is to be called. 83 * @param int $priority optional. Used to specify the order in which the functions associated with a 84 * particular action are executed (default=10, lower=earlier execution, and functions 85 * with the same priority are executed in the order in which they were added to the 86 * filter) 87 * @param int $accepted_args optional. The number of arguments the function accept (default is the number 88 * provided). 89 * @param string $type 90 * @global array $yourls_filters Storage for all of the filters 91 * @return void 92 */ 93 function yourls_add_filter( $hook, $function_name, $priority = 10, $accepted_args = NULL, $type = 'filter' ) { 94 global $yourls_filters; 95 // At this point, we cannot check if the function exists, as it may well be defined later (which is OK) 96 $id = yourls_filter_unique_id($function_name); 97 98 $yourls_filters[ $hook ][ $priority ][ $id ] = [ 99 'function' => $function_name, 100 'accepted_args' => $accepted_args, 101 'type' => $type, 102 ]; 103 } 104 105 /** 106 * Hooks a function on to a specific action. 107 * 108 * Actions are the hooks that YOURLS launches at specific points 109 * during execution, or when specific events occur. Plugins can specify that 110 * one or more of its PHP functions are executed at these points, using the 111 * Action API. 112 * 113 * Typical use: 114 * yourls_add_action('some_hook', 'function_handler_for_hook'); 115 * 116 * @link https://docs.yourls.org/development/plugins.html 117 * @param string $hook The name of the action to which the $function_to_add is hooked. 118 * @param callable $function_name The name of the function you wish to be called. 119 * @param int $priority Optional. Used to specify the order in which the functions associated with a particular action 120 * are executed (default: 10). Lower numbers correspond with earlier execution, and functions 121 * with the same priority are executed in the order in which they were added to the action. 122 * @param int $accepted_args Optional. The number of arguments the function accept (default 1). 123 * @return void 124 */ 125 function yourls_add_action( $hook, $function_name, $priority = 10, $accepted_args = 1 ) { 126 yourls_add_filter( $hook, $function_name, $priority, $accepted_args, 'action' ); 127 } 128 129 /** 130 * Build Unique ID for storage and retrieval. 131 * 132 * Simply using a function name is not enough, as several functions can have the same name when they are enclosed in classes. 133 * Possible ways to attach a function to a hook (filter or action): 134 * - strings: 135 * yourls_add_filter('my_hook_test', 'my_callback_function'); 136 * yourls_add_filter('my_hook_test', 'My_Class::my_callback_function'); 137 * 138 * - arrays: 139 * yourls_add_filter('my_hook_test', array('My_Class','my_callback_function')); 140 * yourls_add_filter('my_hook_test', array($class_instance, 'my_callback_function')); 141 * 142 * - objects: 143 * yourls_add_filter('my_hook_test', $class_instance_with_invoke_method); 144 * yourls_add_filter('my_hook_test', $my_callback_function); 145 * 146 * @link https://docs.yourls.org/development/hooks.html 147 * @param string|array|object $function The callable used in a filter or action. 148 * @return string unique ID for usage as array key 149 */ 150 function yourls_filter_unique_id($function) { 151 // If given a string (function name) 152 if ( is_string( $function ) ) { 153 return $function; 154 } 155 156 if ( is_object( $function ) ) { 157 // Closures are implemented as objects 158 $function = [ $function, '' ]; 159 } 160 else { 161 $function = (array)$function; 162 } 163 164 // Object Class Calling 165 if ( is_object( $function[0] ) ) { 166 return spl_object_hash( $function[0] ).$function[1]; 167 } 168 169 // Last case, static Calling : $function[0] is a string (Class Name) and $function[1] is a string (Method Name) 170 return $function[0].'::'.$function[1]; 171 } 172 173 /** 174 * Performs a filtering operation on a value or an event. 175 * 176 * Typical use: 177 * 178 * 1) Modify a variable if a function is attached to hook 'yourls_hook' 179 * $yourls_var = "default value"; 180 * $yourls_var = yourls_apply_filter( 'yourls_hook', $yourls_var ); 181 * 182 * 2) Trigger functions is attached to event 'yourls_event' 183 * yourls_apply_filter( 'yourls_event' ); 184 * (see yourls_do_action() ) 185 * 186 * Returns a value which may have been modified by a filter. 187 * 188 * @global array $yourls_filters storage for all of the filters 189 * @param string $hook the name of the YOURLS element or action 190 * @param mixed $value the value of the element before filtering 191 * @param true|mixed $is_action true if the function is called by yourls_do_action() - otherwise may be the second parameter of an arbitrary number of parameters 192 * @return mixed 193 */ 194 function yourls_apply_filter( $hook, $value = '', $is_action = false ) { 195 global $yourls_filters; 196 197 $args = func_get_args(); 198 199 // Do 'all' filters first. We check if $is_action to avoid calling `yourls_call_all_hooks()` twice 200 if ( !$is_action && isset($yourls_filters['all']) ) { 201 yourls_call_all_hooks('filter', $hook, $args); 202 } 203 204 // If we have no hook attached to that filter, just return unmodified $value 205 if ( !isset( $yourls_filters[ $hook ] ) ) { 206 return $value; 207 } 208 209 // Sort filters by priority 210 ksort( $yourls_filters[ $hook ] ); 211 212 // Loops through each filter 213 reset( $yourls_filters[ $hook ] ); 214 do { 215 foreach ( (array)current( $yourls_filters[ $hook ] ) as $the_ ) { 216 $_value = ''; 217 if ( !is_null($the_[ 'function' ]) ) { 218 $args[ 1 ] = $value; 219 $count = $the_[ 'accepted_args' ]; 220 if ( is_null( $count ) ) { 221 $_value = call_user_func_array( $the_[ 'function' ], array_slice( $args, 1 ) ); 222 } 223 else { 224 $_value = call_user_func_array( $the_[ 'function' ], array_slice( $args, 1, (int)$count ) ); 225 } 226 } 227 if ( $the_[ 'type' ] == 'filter' ) { 228 $value = $_value; 229 } 230 } 231 } while ( next( $yourls_filters[ $hook ] ) !== false ); 232 233 // Return the value - this will be actually used only for filters, not for actions (see `yourls_do_action()`) 234 return $value; 235 } 236 237 /** 238 * Performs an action triggered by a YOURLS event. 239 * 240 * @param string $hook the name of the YOURLS action 241 * @param mixed $arg action arguments 242 * @return void 243 */ 244 function yourls_do_action( $hook, $arg = '' ) { 245 global $yourls_actions, $yourls_filters; 246 247 // Keep track of actions that are "done" 248 if ( !isset( $yourls_actions ) ) { 249 $yourls_actions = []; 250 } 251 if ( !isset( $yourls_actions[ $hook ] ) ) { 252 $yourls_actions[ $hook ] = 1; 253 } 254 else { 255 ++$yourls_actions[ $hook ]; 256 } 257 258 $args = []; 259 if ( is_array( $arg ) && 1 == count( $arg ) && isset( $arg[ 0 ] ) && is_object( $arg[ 0 ] ) ) { // array(&$this) 260 $args[] =& $arg[ 0 ]; 261 } 262 else { 263 $args[] = $arg; 264 } 265 266 for ( $a = 2 ; $a < func_num_args() ; $a++ ) { 267 $args[] = func_get_arg( $a ); 268 } 269 270 // Do 'all' actions first 271 if ( isset($yourls_filters['all']) ) { 272 yourls_call_all_hooks('action', $hook, $args); 273 } 274 275 yourls_apply_filter( $hook, $args, true ); 276 } 277 278 /** 279 * Retrieve the number times an action is fired. 280 * 281 * @param string $hook Name of the action hook. 282 * @return int The number of times action hook <tt>$hook</tt> is fired 283 */ 284 function yourls_did_action( $hook ) { 285 global $yourls_actions; 286 return empty( $yourls_actions[ $hook ] ) ? 0 : $yourls_actions[ $hook ]; 287 } 288 289 /** 290 * Execute the 'all' hook, with all of the arguments or parameters that were used for the hook 291 * 292 * Internal function used by yourls_do_action() and yourls_apply_filter() - not meant to be used from 293 * outside these functions. 294 * This is mostly a debugging function to understand the flow of events. 295 * See https://docs.yourls.org/development/debugging.html to learn how to use the 'all' hook 296 * 297 * @link https://docs.yourls.org/development/debugging.html 298 * @since 1.8.1 299 * @param string $type Either 'action' or 'filter' 300 * @param string $hook The hook name, eg 'plugins_loaded' 301 * @param mixed $args Variable-length argument lists that were passed to the action or filter 302 * @return void 303 */ 304 function yourls_call_all_hooks($type, $hook, ...$args) { 305 global $yourls_filters; 306 307 // Loops through each filter or action hooked with the 'all' hook 308 reset( $yourls_filters['all'] ); 309 do { 310 foreach ( (array) current($yourls_filters['all']) as $the_ ) 311 // Call the hooked function only if it's hooked to the current type of hook (eg 'filter' or 'action') 312 if ( $the_['type'] == $type && !is_null($the_['function']) ) { 313 call_user_func_array( $the_['function'], array($type, $hook, $args) ); 314 /** 315 * Note that we don't return a value here, regardless of $type being an action (obviously) but also 316 * a filter. Indeed it would not make sense to actually "filter" and return values when we're 317 * feeding the same function every single hook in YOURLS, no matter their parameters. 318 */ 319 } 320 321 } while ( next($yourls_filters['all']) !== false ); 322 323 } 324 325 /** 326 * Removes a function from a specified filter hook. 327 * 328 * This function removes a function attached to a specified filter hook. This 329 * method can be used to remove default functions attached to a specific filter 330 * hook and possibly replace them with a substitute. 331 * 332 * To remove a hook, the $function_to_remove and $priority arguments must match 333 * when the hook was added. 334 * 335 * @global array $yourls_filters storage for all of the filters 336 * @param string $hook The filter hook to which the function to be removed is hooked. 337 * @param callable $function_to_remove The name of the function which should be removed. 338 * @param int $priority optional. The priority of the function (default: 10). 339 * @return bool Whether the function was registered as a filter before it was removed. 340 */ 341 function yourls_remove_filter( $hook, $function_to_remove, $priority = 10 ) { 342 global $yourls_filters; 343 344 $function_to_remove = yourls_filter_unique_id($function_to_remove); 345 346 $remove = isset( $yourls_filters[ $hook ][ $priority ][ $function_to_remove ] ); 347 348 if ( $remove === true ) { 349 unset ( $yourls_filters[ $hook ][ $priority ][ $function_to_remove ] ); 350 if ( empty( $yourls_filters[ $hook ][ $priority ] ) ) { 351 unset( $yourls_filters[ $hook ] ); 352 } 353 } 354 return $remove; 355 } 356 357 /** 358 * Removes a function from a specified action hook. 359 * 360 * @see yourls_remove_filter() 361 * @since 1.7.1 362 * @param string $hook The action hook to which the function to be removed is hooked. 363 * @param callable $function_to_remove The name of the function which should be removed. 364 * @param int $priority optional. The priority of the function (default: 10). 365 * @return bool Whether the function was registered as an action before it was removed. 366 */ 367 function yourls_remove_action( $hook, $function_to_remove, $priority = 10 ) { 368 return yourls_remove_filter( $hook, $function_to_remove, $priority ); 369 } 370 371 /** 372 * Removes all functions from a specified action hook. 373 * 374 * @see yourls_remove_all_filters() 375 * @since 1.7.1 376 * @param string $hook The action to remove hooks from 377 * @param int|false $priority optional. The priority of the functions to remove 378 * @return bool true when it's finished 379 */ 380 function yourls_remove_all_actions( $hook, $priority = false ) { 381 return yourls_remove_all_filters( $hook, $priority ); 382 } 383 384 /** 385 * Removes all functions from a specified filter hook. 386 * 387 * @since 1.7.1 388 * @param string $hook The filter to remove hooks from 389 * @param int|false $priority optional. The priority of the functions to remove 390 * @return bool true when it's finished 391 */ 392 function yourls_remove_all_filters( $hook, $priority = false ) { 393 global $yourls_filters; 394 395 if ( isset( $yourls_filters[ $hook ] ) ) { 396 if ( $priority === false ) { 397 unset( $yourls_filters[ $hook ] ); 398 } 399 elseif ( isset( $yourls_filters[ $hook ][ $priority ] ) ) { 400 unset( $yourls_filters[ $hook ][ $priority ] ); 401 } 402 } 403 404 return true; 405 } 406 407 /** 408 * Return filters for a specific hook. 409 * 410 * If hook has filters (or actions, see yourls_has_action()), this will return an array priorities => callbacks. 411 * See the structure of yourls_filters on top of this file for details. 412 * 413 * @since 1.8.3 414 * @param string $hook The hook to retrieve filters for 415 * @return array 416 */ 417 function yourls_get_filters($hook) { 418 global $yourls_filters; 419 return $yourls_filters[$hook] ?? array(); 420 } 421 422 /** 423 * Return actions for a specific hook. 424 * 425 * @since 1.8.3 426 * @param string $hook The hook to retrieve actions for 427 * @return array 428 */ 429 function yourls_get_actions($hook) { 430 return yourls_get_filters($hook); 431 } 432 /** 433 * Check if any filter has been registered for a hook. 434 * 435 * @since 1.5 436 * @global array $yourls_filters storage for all of the filters 437 * @param string $hook The name of the filter hook. 438 * @param callable|false $function_to_check optional. If specified, return the priority of that function on this hook or false if not attached. 439 * @return int|bool Optionally returns the priority on that hook for the specified function. 440 */ 441 function yourls_has_filter( $hook, $function_to_check = false ) { 442 global $yourls_filters; 443 444 $has = !empty( $yourls_filters[ $hook ] ); 445 if ( false === $function_to_check || false === $has ) { 446 return $has; 447 } 448 449 if ( !$idx = yourls_filter_unique_id($function_to_check) ) { 450 return false; 451 } 452 453 foreach ( array_keys( $yourls_filters[ $hook ] ) as $priority ) { 454 if ( isset( $yourls_filters[ $hook ][ $priority ][ $idx ] ) ) { 455 return $priority; 456 } 457 } 458 return false; 459 } 460 461 462 /** 463 * Check if any action has been registered for a hook. 464 * 465 * @since 1.5 466 * @param string $hook 467 * @param callable|false $function_to_check 468 * @return bool|int 469 */ 470 function yourls_has_action( $hook, $function_to_check = false ) { 471 return yourls_has_filter( $hook, $function_to_check ); 472 } 473 474 /** 475 * Return number of active plugins 476 * 477 * @return int Number of activated plugins 478 */ 479 function yourls_has_active_plugins() { 480 return count( yourls_get_db()->get_plugins() ); 481 } 482 483 /** 484 * List plugins in /user/plugins 485 * 486 * @return array Array of [/plugindir/plugin.php]=>array('Name'=>'Ozh', 'Title'=>'Hello', ) 487 */ 488 function yourls_get_plugins() { 489 $plugins = (array)glob( YOURLS_PLUGINDIR.'/*/plugin.php' ); 490 491 if ( is_array( $plugins ) ) { 492 foreach ( $plugins as $key => $plugin ) { 493 $plugins[ yourls_plugin_basename( $plugin ) ] = yourls_get_plugin_data( $plugin ); 494 unset( $plugins[ $key ] ); 495 } 496 } 497 498 return empty( $plugins ) ? [] : $plugins; 499 } 500 501 /** 502 * Check if a plugin is active 503 * 504 * @param string $plugin Physical path to plugin file 505 * @return bool 506 */ 507 function yourls_is_active_plugin( $plugin ) { 508 return yourls_has_active_plugins() > 0 ? 509 in_array( yourls_plugin_basename( $plugin ), yourls_get_db()->get_plugins() ) 510 : false; 511 } 512 513 /** 514 * Parse a plugin header 515 * 516 * The plugin header has the following form: 517 * /* 518 * Plugin Name: <plugin name> 519 * Plugin URI: <plugin home page> 520 * Description: <plugin description> 521 * Version: <plugin version number> 522 * Author: <author name> 523 * Author URI: <author home page> 524 * * / 525 * 526 * Or in the form of a phpdoc block 527 * /** 528 * * Plugin Name: <plugin name> 529 * * Plugin URI: <plugin home page> 530 * * Description: <plugin description> 531 * * Version: <plugin version number> 532 * * Author: <author name> 533 * * Author URI: <author home page> 534 * * / 535 * 536 * @since 1.5 537 * @param string $file Physical path to plugin file 538 * @return array Array of 'Field'=>'Value' from plugin comment header lines of the form "Field: Value" 539 */ 540 function yourls_get_plugin_data( $file ) { 541 $fp = fopen( $file, 'r' ); // assuming $file is readable, since yourls_load_plugins() filters this 542 $data = fread( $fp, 8192 ); // get first 8kb 543 fclose( $fp ); 544 545 // Capture all the header within first comment block 546 if ( !preg_match( '!.*?/\*(.*?)\*/!ms', $data, $matches ) ) { 547 return []; 548 } 549 550 // Capture each line with "Something: some text" 551 unset( $data ); 552 $lines = preg_split( "[\n|\r]", $matches[ 1 ] ); 553 unset( $matches ); 554 555 $plugin_data = []; 556 foreach ( $lines as $line ) { 557 if ( !preg_match( '!(\s*)?\*?(\s*)?(.*?):\s+(.*)!', $line, $matches ) ) { 558 continue; 559 } 560 561 $plugin_data[ trim($matches[3]) ] = yourls_esc_html(trim($matches[4])); 562 } 563 564 return $plugin_data; 565 } 566 567 /** 568 * Include active plugins 569 * 570 * This function includes every 'YOURLS_PLUGINDIR/plugin_name/plugin.php' found in option 'active_plugins' 571 * It will return a diagnosis array with the following keys: 572 * (bool)'loaded' : true if plugin(s) loaded, false otherwise 573 * (string)'info' : extra information 574 * 575 * @since 1.5 576 * @return array Array('loaded' => bool, 'info' => string) 577 */ 578 function yourls_load_plugins() { 579 // Don't load plugins when installing or updating 580 if ( yourls_is_installing() OR yourls_is_upgrading() OR !yourls_is_installed() ) { 581 return [ 582 'loaded' => false, 583 'info' => 'install/upgrade' 584 ]; 585 } 586 587 $active_plugins = (array)yourls_get_option( 'active_plugins' ); 588 if ( empty( $active_plugins ) ) { 589 return [ 590 'loaded' => false, 591 'info' => 'no active plugin' 592 ]; 593 } 594 595 $plugins = []; 596 foreach ( $active_plugins as $key => $plugin ) { 597 $file = YOURLS_PLUGINDIR . '/' . $plugin; 598 if ( yourls_is_a_plugin_file($file) && yourls_include_file_sandbox( $file ) === true ) { 599 $plugins[] = $plugin; 600 unset( $active_plugins[ $key ] ); 601 } 602 } 603 604 // Replace active plugin list with list of plugins we just activated 605 yourls_get_db()->set_plugins( $plugins ); 606 $info = count( $plugins ).' activated'; 607 608 // $active_plugins should be empty now, if not, a plugin could not be found, or is erroneous : remove it 609 $missing_count = count( $active_plugins ); 610 if ( $missing_count > 0 ) { 611 yourls_update_option( 'active_plugins', $plugins ); 612 $message = yourls_n( 'Could not find and deactivate plugin :', 'Could not find and deactivate plugins :', $missing_count ); 613 $missing = '<strong>'.implode( '</strong>, <strong>', $active_plugins ).'</strong>'; 614 yourls_add_notice( $message.' '.$missing ); 615 $info .= ', '.$missing_count.' removed'; 616 } 617 618 return [ 619 'loaded' => true, 620 'info' => $info 621 ]; 622 } 623 624 /** 625 * Check if a file is a plugin file 626 * 627 * This doesn't check if the file is a valid PHP file, only that it's correctly named. 628 * 629 * @since 1.5 630 * @param string $file Full pathname to a file 631 * @return bool 632 */ 633 function yourls_is_a_plugin_file($file) { 634 return false === strpos( $file, '..' ) 635 && false === strpos( $file, './' ) 636 && 'plugin.php' === substr( $file, -10 ) 637 && is_readable( $file ); 638 } 639 640 /** 641 * Activate a plugin 642 * 643 * @since 1.5 644 * @param string $plugin Plugin filename (full or relative to plugins directory) 645 * @return string|true string if error or true if success 646 */ 647 function yourls_activate_plugin( $plugin ) { 648 // validate file 649 $plugin = yourls_plugin_basename( $plugin ); 650 $plugindir = yourls_sanitize_filename( YOURLS_PLUGINDIR ); 651 if ( !yourls_is_a_plugin_file($plugindir . '/' . $plugin ) ) { 652 return yourls__( 'Not a valid plugin file' ); 653 } 654 655 // check not activated already 656 $ydb = yourls_get_db(); 657 if ( yourls_is_active_plugin( $plugin ) ) { 658 return yourls__( 'Plugin already activated' ); 659 } 660 661 // attempt activation. 662 $attempt = yourls_include_file_sandbox( $plugindir.'/'.$plugin ); 663 if( $attempt !== true ) { 664 return yourls_s( 'Plugin generated unexpected output. Error was: <br/><pre>%s</pre>', $attempt ); 665 } 666 667 // so far, so good: update active plugin list 668 $ydb->add_plugin( $plugin ); 669 yourls_update_option( 'active_plugins', $ydb->get_plugins() ); 670 yourls_do_action( 'activated_plugin', $plugin ); 671 yourls_do_action( 'activated_'.$plugin ); 672 673 return true; 674 } 675 676 /** 677 * Deactivate a plugin 678 * 679 * @since 1.5 680 * @param string $plugin Plugin filename (full relative to plugins directory) 681 * @return string|true string if error or true if success 682 */ 683 function yourls_deactivate_plugin( $plugin ) { 684 $plugin = yourls_plugin_basename( $plugin ); 685 686 // Check plugin is active 687 if ( !yourls_is_active_plugin( $plugin ) ) { 688 return yourls__( 'Plugin not active' ); 689 } 690 691 // Check if we have an uninstall file - load if so 692 $uninst_file = YOURLS_PLUGINDIR . '/' . dirname($plugin) . '/uninstall.php'; 693 $attempt = yourls_include_file_sandbox( $uninst_file ); 694 695 // Check if we have an error to display 696 if ( is_string( $attempt ) ) { 697 $message = yourls_s( 'Loading %s generated unexpected output. Error was: <br/><pre>%s</pre>', $uninst_file, $attempt ); 698 return( $message ); 699 } 700 701 if ( $attempt === true ) { 702 define('YOURLS_UNINSTALL_PLUGIN', true); 703 } 704 705 // Deactivate the plugin 706 $ydb = yourls_get_db(); 707 $plugins = $ydb->get_plugins(); 708 $key = array_search( $plugin, $plugins ); 709 if ( $key !== false ) { 710 array_splice( $plugins, $key, 1 ); 711 } 712 713 $ydb->set_plugins( $plugins ); 714 yourls_update_option( 'active_plugins', $plugins ); 715 yourls_do_action( 'deactivated_plugin', $plugin ); 716 yourls_do_action( 'deactivated_'.$plugin ); 717 718 return true; 719 } 720 721 /** 722 * Return the path of a plugin file, relative to the plugins directory 723 * 724 * @since 1.5 725 * @param string $file 726 * @return string 727 */ 728 function yourls_plugin_basename( $file ) { 729 return trim( str_replace( yourls_sanitize_filename( YOURLS_PLUGINDIR ), '', yourls_sanitize_filename( $file ) ), '/' ); 730 } 731 732 /** 733 * Return the URL of the directory a plugin 734 * 735 * @since 1.5 736 * @param string $file 737 * @return string 738 */ 739 function yourls_plugin_url( $file ) { 740 $url = YOURLS_PLUGINURL.'/'.yourls_plugin_basename( $file ); 741 if ( yourls_is_ssl() or yourls_needs_ssl() ) { 742 $url = str_replace( 'http://', 'https://', $url ); 743 } 744 return (string)yourls_apply_filter( 'plugin_url', $url, $file ); 745 } 746 747 /** 748 * Build list of links to plugin admin pages, if any 749 * 750 * @since 1.5 751 * @return array Array of arrays of URL and anchor of plugin admin pages, or empty array if no plugin page 752 */ 753 function yourls_list_plugin_admin_pages() { 754 $plugin_links = []; 755 foreach ( yourls_get_db()->get_plugin_pages() as $plugin => $page ) { 756 $plugin_links[ $plugin ] = [ 757 'url' => yourls_admin_url( 'plugins.php?page='.$page[ 'slug' ] ), 758 'anchor' => $page[ 'title' ], 759 ]; 760 } 761 return $plugin_links; 762 } 763 764 /** 765 * Register a plugin administration page 766 * 767 * @since 1.5 768 * @param string $slug 769 * @param string $title 770 * @param callable $function 771 * @return void 772 */ 773 function yourls_register_plugin_page( $slug, $title, $function ) { 774 yourls_get_db()->add_plugin_page( $slug, $title, $function ); 775 } 776 777 /** 778 * Handle plugin administration page 779 * 780 * @since 1.5 781 * @param string $plugin_page 782 * @return void 783 */ 784 function yourls_plugin_admin_page( $plugin_page ) { 785 // Check the plugin page is actually registered 786 $pages = yourls_get_db()->get_plugin_pages(); 787 if ( !isset( $pages[ $plugin_page ] ) ) { 788 yourls_die( yourls__( 'This page does not exist. Maybe a plugin you thought was activated is inactive?' ), yourls__( 'Invalid link' ) ); 789 } 790 791 // Check the plugin page function is actually callable 792 $page_function = $pages[ $plugin_page ][ 'function' ]; 793 if (!is_callable($page_function)) { 794 yourls_die( yourls__( 'This page cannot be displayed because the displaying function is not callable.' ), yourls__( 'Invalid code' ) ); 795 } 796 797 // Draw the page itself 798 yourls_do_action( 'load-'.$plugin_page ); 799 yourls_html_head( 'plugin_page_'.$plugin_page, $pages[ $plugin_page ][ 'title' ] ); 800 yourls_html_logo(); 801 yourls_html_menu(); 802 803 $page_function( ); 804 805 yourls_html_footer(); 806 } 807 808 /** 809 * Callback function: Sort plugins 810 * 811 * @link http://php.net/uasort 812 * @codeCoverageIgnore 813 * 814 * @since 1.5 815 * @param array $plugin_a 816 * @param array $plugin_b 817 * @return int 0, 1 or -1, see uasort() 818 */ 819 function yourls_plugins_sort_callback( $plugin_a, $plugin_b ) { 820 $orderby = yourls_apply_filter( 'plugins_sort_callback', 'Plugin Name' ); 821 $order = yourls_apply_filter( 'plugins_sort_callback', 'ASC' ); 822 823 $a = isset( $plugin_a[ $orderby ] ) ? $plugin_a[ $orderby ] : ''; 824 $b = isset( $plugin_b[ $orderby ] ) ? $plugin_b[ $orderby ] : ''; 825 826 if ( $a == $b ) { 827 return 0; 828 } 829 830 if ( 'DESC' == $order ) { 831 return ( $a < $b ) ? 1 : -1; 832 } 833 else { 834 return ( $a < $b ) ? -1 : 1; 835 } 836 } 837 838 /** 839 * Shutdown function, runs just before PHP shuts down execution. Stolen from WP 840 * 841 * This function is automatically tied to the script execution end at startup time, see 842 * var $actions->register_shutdown in includes/Config/Init.php 843 * 844 * You can use this function to fire one or several actions when the PHP execution ends. 845 * Example of use: 846 * yourls_add_action('shutdown', 'my_plugin_action_this'); 847 * yourls_add_action('shutdown', 'my_plugin_action_that'); 848 * // functions my_plugin_action_this() and my_plugin_action_that() will be triggered 849 * // after YOURLS is completely executed 850 * 851 * @codeCoverageIgnore 852 * @since 1.5.1 853 * @return void 854 */ 855 function yourls_shutdown() { 856 yourls_do_action( 'shutdown' ); 857 } 858 859 /** 860 * Returns true. 861 * 862 * Useful for returning true to filters easily. 863 * 864 * @since 1.7.1 865 * @return bool True. 866 */ 867 function yourls_return_true() { 868 return true; 869 } 870 871 /** 872 * Returns false. 873 * 874 * Useful for returning false to filters easily. 875 * 876 * @since 1.7.1 877 * @return bool False. 878 */ 879 function yourls_return_false() { 880 return false; 881 } 882 883 /** 884 * Returns 0. 885 * 886 * Useful for returning 0 to filters easily. 887 * 888 * @since 1.7.1 889 * @return int 0. 890 */ 891 function yourls_return_zero() { 892 return 0; 893 } 894 895 /** 896 * Returns an empty array. 897 * 898 * Useful for returning an empty array to filters easily. 899 * 900 * @since 1.7.1 901 * @return array Empty array. 902 */ 903 function yourls_return_empty_array() { 904 return []; 905 } 906 907 /** 908 * Returns null. 909 * 910 * Useful for returning null to filters easily. 911 * 912 * @since 1.7.1 913 * @return null Null value. 914 */ 915 function yourls_return_null() { 916 return null; 917 } 918 919 /** 920 * Returns an empty string. 921 * 922 * Useful for returning an empty string to filters easily. 923 * 924 * @since 1.7.1 925 * @return string Empty string. 926 */ 927 function yourls_return_empty_string() { 928 return ''; 929 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sat Feb 22 05:10:06 2025 | Cross-referenced by PHPXref 0.7.1 |