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