/wp-includes/plugin.php

  1. <?php 
  2. /** 
  3. * The plugin API is located in this file, which allows for creating actions 
  4. * and filters and hooking functions, and methods. The functions or methods will 
  5. * then be run when the action or filter is called. 
  6. * 
  7. * The API callback examples reference functions, but can be methods of classes. 
  8. * To hook methods, you'll need to pass an array one of two ways. 
  9. * 
  10. * Any of the syntaxes explained in the PHP documentation for the 
  11. * {@link https://secure.php.net/manual/en/language.pseudo-types.php#language.types.callback 'callback'} 
  12. * type are valid. 
  13. * 
  14. * Also see the {@link https://codex.wordpress.org/Plugin_API Plugin API} for 
  15. * more information and examples on how to use a lot of these functions. 
  16. * 
  17. * This file should have no external dependencies. 
  18. * 
  19. * @package WordPress 
  20. * @subpackage Plugin 
  21. * @since 1.5.0 
  22. */ 
  23.  
  24. // Initialize the filter globals. 
  25. require( dirname( __FILE__ ) . '/class-wp-hook.php' ); 
  26.  
  27. /** @var WP_Hook[] $wp_filter */ 
  28. global $wp_filter, $wp_actions, $wp_current_filter; 
  29.  
  30. if ( $wp_filter ) { 
  31. $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter ); 
  32. } else { 
  33. $wp_filter = array(); 
  34.  
  35. if ( ! isset( $wp_actions ) ) 
  36. $wp_actions = array(); 
  37.  
  38. if ( ! isset( $wp_current_filter ) ) 
  39. $wp_current_filter = array(); 
  40.  
  41. /** 
  42. * Hook a function or method to a specific filter action. 
  43. * 
  44. * WordPress offers filter hooks to allow plugins to modify 
  45. * various types of internal data at runtime. 
  46. * 
  47. * A plugin can modify data by binding a callback to a filter hook. When the filter 
  48. * is later applied, each bound callback is run in order of priority, and given 
  49. * the opportunity to modify a value by returning a new value. 
  50. * 
  51. * The following example shows how a callback function is bound to a filter hook. 
  52. * 
  53. * Note that `$example` is passed to the callback, (maybe) modified, then returned: 
  54. * 
  55. * function example_callback( $example ) { 
  56. * // Maybe modify $example in some way. 
  57. * return $example; 
  58. * } 
  59. * add_filter( 'example_filter', 'example_callback' ); 
  60. * 
  61. * Bound callbacks can accept from none to the total number of arguments passed as parameters 
  62. * in the corresponding apply_filters() call. 
  63. * 
  64. * In other words, if an apply_filters() call passes four total arguments, callbacks bound to 
  65. * it can accept none (the same as 1) of the arguments or up to four. The important part is that 
  66. * the `$accepted_args` value must reflect the number of arguments the bound callback *actually* 
  67. * opted to accept. If no arguments were accepted by the callback that is considered to be the 
  68. * same as accepting 1 argument. For example: 
  69. * 
  70. * // Filter call. 
  71. * $value = apply_filters( 'hook', $value, $arg2, $arg3 ); 
  72. * 
  73. * // Accepting zero/one arguments. 
  74. * function example_callback() { 
  75. * ... 
  76. * return 'some value'; 
  77. * } 
  78. * add_filter( 'hook', 'example_callback' ); // Where $priority is default 10, $accepted_args is default 1. 
  79. * 
  80. * // Accepting two arguments (three possible). 
  81. * function example_callback( $value, $arg2 ) { 
  82. * ... 
  83. * return $maybe_modified_value; 
  84. * } 
  85. * add_filter( 'hook', 'example_callback', 10, 2 ); // Where $priority is 10, $accepted_args is 2. 
  86. * 
  87. * *Note:* The function will return true whether or not the callback is valid. 
  88. * It is up to you to take care. This is done for optimization purposes, so 
  89. * everything is as quick as possible. 
  90. * 
  91. * @since 0.71 
  92. * 
  93. * @global array $wp_filter A multidimensional array of all hooks and the callbacks hooked to them. 
  94. * 
  95. * @param string $tag The name of the filter to hook the $function_to_add callback to. 
  96. * @param callable $function_to_add The callback to be run when the filter is applied. 
  97. * @param int $priority Optional. Used to specify the order in which the functions 
  98. * associated with a particular action are executed. Default 10. 
  99. * Lower numbers correspond with earlier execution,  
  100. * and functions with the same priority are executed 
  101. * in the order in which they were added to the action. 
  102. * @param int $accepted_args Optional. The number of arguments the function accepts. Default 1. 
  103. * @return true 
  104. */ 
  105. function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) { 
  106. global $wp_filter; 
  107. if ( ! isset( $wp_filter[ $tag ] ) ) { 
  108. $wp_filter[ $tag ] = new WP_Hook(); 
  109. $wp_filter[ $tag ]->add_filter( $tag, $function_to_add, $priority, $accepted_args ); 
  110. return true; 
  111.  
  112. /** 
  113. * Check if any filter has been registered for a hook. 
  114. * 
  115. * @since 2.5.0 
  116. * 
  117. * @global array $wp_filter Stores all of the filters. 
  118. * 
  119. * @param string $tag The name of the filter hook. 
  120. * @param callable|bool $function_to_check Optional. The callback to check for. Default false. 
  121. * @return false|int If $function_to_check is omitted, returns boolean for whether the hook has 
  122. * anything registered. When checking a specific function, the priority of that 
  123. * hook is returned, or false if the function is not attached. When using the 
  124. * $function_to_check argument, this function may return a non-boolean value 
  125. * that evaluates to false (e.g.) 0, so use the === operator for testing the 
  126. * return value. 
  127. */ 
  128. function has_filter($tag, $function_to_check = false) { 
  129. global $wp_filter; 
  130.  
  131. if ( ! isset( $wp_filter[ $tag ] ) ) { 
  132. return false; 
  133.  
  134. return $wp_filter[ $tag ]->has_filter( $tag, $function_to_check ); 
  135.  
  136. /** 
  137. * Call the functions added to a filter hook. 
  138. * 
  139. * The callback functions attached to filter hook $tag are invoked by calling 
  140. * this function. This function can be used to create a new filter hook by 
  141. * simply calling this function with the name of the new hook specified using 
  142. * the $tag parameter. 
  143. * 
  144. * The function allows for additional arguments to be added and passed to hooks. 
  145. * 
  146. * // Our filter callback function 
  147. * function example_callback( $string, $arg1, $arg2 ) { 
  148. * // (maybe) modify $string 
  149. * return $string; 
  150. * } 
  151. * add_filter( 'example_filter', 'example_callback', 10, 3 ); 
  152. * 
  153. * /** 
  154. * * Apply the filters by calling the 'example_callback' function we 
  155. * * "hooked" to 'example_filter' using the add_filter() function above. 
  156. * * - 'example_filter' is the filter hook $tag 
  157. * * - 'filter me' is the value being filtered 
  158. * * - $arg1 and $arg2 are the additional arguments passed to the callback. 
  159. * $value = apply_filters( 'example_filter', 'filter me', $arg1, $arg2 ); 
  160. * 
  161. * @since 0.71 
  162. * 
  163. * @global array $wp_filter Stores all of the filters. 
  164. * @global array $wp_current_filter Stores the list of current filters with the current one last. 
  165. * 
  166. * @param string $tag The name of the filter hook. 
  167. * @param mixed $value The value on which the filters hooked to `$tag` are applied on. 
  168. * @param mixed $var, ... Additional variables passed to the functions hooked to `$tag`. 
  169. * @return mixed The filtered value after all hooked functions are applied to it. 
  170. */ 
  171. function apply_filters( $tag, $value ) { 
  172. global $wp_filter, $wp_current_filter; 
  173.  
  174. $args = array(); 
  175.  
  176. // Do 'all' actions first. 
  177. if ( isset($wp_filter['all']) ) { 
  178. $wp_current_filter[] = $tag; 
  179. $args = func_get_args(); 
  180. _wp_call_all_hook($args); 
  181.  
  182. if ( !isset($wp_filter[$tag]) ) { 
  183. if ( isset($wp_filter['all']) ) 
  184. array_pop($wp_current_filter); 
  185. return $value; 
  186.  
  187. if ( !isset($wp_filter['all']) ) 
  188. $wp_current_filter[] = $tag; 
  189.  
  190. if ( empty($args) ) 
  191. $args = func_get_args(); 
  192.  
  193. // don't pass the tag name to WP_Hook 
  194. array_shift( $args ); 
  195.  
  196. $filtered = $wp_filter[ $tag ]->apply_filters( $value, $args ); 
  197.  
  198. array_pop( $wp_current_filter ); 
  199.  
  200. return $filtered; 
  201.  
  202. /** 
  203. * Execute functions hooked on a specific filter hook, specifying arguments in an array. 
  204. * 
  205. * @since 3.0.0 
  206. * 
  207. * @see apply_filters() This function is identical, but the arguments passed to the 
  208. * functions hooked to `$tag` are supplied using an array. 
  209. * 
  210. * @global array $wp_filter Stores all of the filters 
  211. * @global array $wp_current_filter Stores the list of current filters with the current one last 
  212. * 
  213. * @param string $tag The name of the filter hook. 
  214. * @param array $args The arguments supplied to the functions hooked to $tag. 
  215. * @return mixed The filtered value after all hooked functions are applied to it. 
  216. */ 
  217. function apply_filters_ref_array($tag, $args) { 
  218. global $wp_filter, $wp_current_filter; 
  219.  
  220. // Do 'all' actions first 
  221. if ( isset($wp_filter['all']) ) { 
  222. $wp_current_filter[] = $tag; 
  223. $all_args = func_get_args(); 
  224. _wp_call_all_hook($all_args); 
  225.  
  226. if ( !isset($wp_filter[$tag]) ) { 
  227. if ( isset($wp_filter['all']) ) 
  228. array_pop($wp_current_filter); 
  229. return $args[0]; 
  230.  
  231. if ( !isset($wp_filter['all']) ) 
  232. $wp_current_filter[] = $tag; 
  233.  
  234. $filtered = $wp_filter[ $tag ]->apply_filters( $args[0], $args ); 
  235.  
  236. array_pop( $wp_current_filter ); 
  237.  
  238. return $filtered; 
  239.  
  240. /** 
  241. * Removes a function from a specified filter hook. 
  242. * 
  243. * This function removes a function attached to a specified filter hook. This 
  244. * method can be used to remove default functions attached to a specific filter 
  245. * hook and possibly replace them with a substitute. 
  246. * 
  247. * To remove a hook, the $function_to_remove and $priority arguments must match 
  248. * when the hook was added. This goes for both filters and actions. No warning 
  249. * will be given on removal failure. 
  250. * 
  251. * @since 1.2.0 
  252. * 
  253. * @global array $wp_filter Stores all of the filters 
  254. * 
  255. * @param string $tag The filter hook to which the function to be removed is hooked. 
  256. * @param callable $function_to_remove The name of the function which should be removed. 
  257. * @param int $priority Optional. The priority of the function. Default 10. 
  258. * @return bool Whether the function existed before it was removed. 
  259. */ 
  260. function remove_filter( $tag, $function_to_remove, $priority = 10 ) { 
  261. global $wp_filter; 
  262.  
  263. $r = false; 
  264. if ( isset( $wp_filter[ $tag ] ) ) { 
  265. $r = $wp_filter[ $tag ]->remove_filter( $tag, $function_to_remove, $priority ); 
  266. if ( ! $wp_filter[ $tag ]->callbacks ) { 
  267. unset( $wp_filter[ $tag ] ); 
  268.  
  269. return $r; 
  270.  
  271. /** 
  272. * Remove all of the hooks from a filter. 
  273. * 
  274. * @since 2.7.0 
  275. * 
  276. * @global array $wp_filter Stores all of the filters 
  277. * 
  278. * @param string $tag The filter to remove hooks from. 
  279. * @param int|bool $priority Optional. The priority number to remove. Default false. 
  280. * @return true True when finished. 
  281. */ 
  282. function remove_all_filters( $tag, $priority = false ) { 
  283. global $wp_filter; 
  284.  
  285. if ( isset( $wp_filter[ $tag ]) ) { 
  286. $wp_filter[ $tag ]->remove_all_filters( $priority ); 
  287. if ( ! $wp_filter[ $tag ]->has_filters() ) { 
  288. unset( $wp_filter[ $tag ] ); 
  289.  
  290. return true; 
  291.  
  292. /** 
  293. * Retrieve the name of the current filter or action. 
  294. * 
  295. * @since 2.5.0 
  296. * 
  297. * @global array $wp_current_filter Stores the list of current filters with the current one last 
  298. * 
  299. * @return string Hook name of the current filter or action. 
  300. */ 
  301. function current_filter() { 
  302. global $wp_current_filter; 
  303. return end( $wp_current_filter ); 
  304.  
  305. /** 
  306. * Retrieve the name of the current action. 
  307. * 
  308. * @since 3.9.0 
  309. * 
  310. * @return string Hook name of the current action. 
  311. */ 
  312. function current_action() { 
  313. return current_filter(); 
  314.  
  315. /** 
  316. * Retrieve the name of a filter currently being processed. 
  317. * 
  318. * The function current_filter() only returns the most recent filter or action 
  319. * being executed. did_action() returns true once the action is initially 
  320. * processed. 
  321. * 
  322. * This function allows detection for any filter currently being 
  323. * executed (despite not being the most recent filter to fire, in the case of 
  324. * hooks called from hook callbacks) to be verified. 
  325. * 
  326. * @since 3.9.0 
  327. * 
  328. * @see current_filter() 
  329. * @see did_action() 
  330. * @global array $wp_current_filter Current filter. 
  331. * 
  332. * @param null|string $filter Optional. Filter to check. Defaults to null, which 
  333. * checks if any filter is currently being run. 
  334. * @return bool Whether the filter is currently in the stack. 
  335. */ 
  336. function doing_filter( $filter = null ) { 
  337. global $wp_current_filter; 
  338.  
  339. if ( null === $filter ) { 
  340. return ! empty( $wp_current_filter ); 
  341.  
  342. return in_array( $filter, $wp_current_filter ); 
  343.  
  344. /** 
  345. * Retrieve the name of an action currently being processed. 
  346. * 
  347. * @since 3.9.0 
  348. * 
  349. * @param string|null $action Optional. Action to check. Defaults to null, which checks 
  350. * if any action is currently being run. 
  351. * @return bool Whether the action is currently in the stack. 
  352. */ 
  353. function doing_action( $action = null ) { 
  354. return doing_filter( $action ); 
  355.  
  356. /** 
  357. * Hooks a function on to a specific action. 
  358. * 
  359. * Actions are the hooks that the WordPress core launches at specific points 
  360. * during execution, or when specific events occur. Plugins can specify that 
  361. * one or more of its PHP functions are executed at these points, using the 
  362. * Action API. 
  363. * 
  364. * @since 1.2.0 
  365. * 
  366. * @param string $tag The name of the action to which the $function_to_add is hooked. 
  367. * @param callable $function_to_add The name of the function you wish to be called. 
  368. * @param int $priority Optional. Used to specify the order in which the functions 
  369. * associated with a particular action are executed. Default 10. 
  370. * Lower numbers correspond with earlier execution,  
  371. * and functions with the same priority are executed 
  372. * in the order in which they were added to the action. 
  373. * @param int $accepted_args Optional. The number of arguments the function accepts. Default 1. 
  374. * @return true Will always return true. 
  375. */ 
  376. function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) { 
  377. return add_filter($tag, $function_to_add, $priority, $accepted_args); 
  378.  
  379. /** 
  380. * Execute functions hooked on a specific action hook. 
  381. * 
  382. * This function invokes all functions attached to action hook `$tag`. It is 
  383. * possible to create new action hooks by simply calling this function,  
  384. * specifying the name of the new hook using the `$tag` parameter. 
  385. * 
  386. * You can pass extra arguments to the hooks, much like you can with apply_filters(). 
  387. * 
  388. * @since 1.2.0 
  389. * 
  390. * @global array $wp_filter Stores all of the filters 
  391. * @global array $wp_actions Increments the amount of times action was triggered. 
  392. * @global array $wp_current_filter Stores the list of current filters with the current one last 
  393. * 
  394. * @param string $tag The name of the action to be executed. 
  395. * @param mixed $arg, ... Optional. Additional arguments which are passed on to the 
  396. * functions hooked to the action. Default empty. 
  397. */ 
  398. function do_action($tag, $arg = '') { 
  399. global $wp_filter, $wp_actions, $wp_current_filter; 
  400.  
  401. if ( ! isset($wp_actions[$tag]) ) 
  402. $wp_actions[$tag] = 1; 
  403. else 
  404. ++$wp_actions[$tag]; 
  405.  
  406. // Do 'all' actions first 
  407. if ( isset($wp_filter['all']) ) { 
  408. $wp_current_filter[] = $tag; 
  409. $all_args = func_get_args(); 
  410. _wp_call_all_hook($all_args); 
  411.  
  412. if ( !isset($wp_filter[$tag]) ) { 
  413. if ( isset($wp_filter['all']) ) 
  414. array_pop($wp_current_filter); 
  415. return; 
  416.  
  417. if ( !isset($wp_filter['all']) ) 
  418. $wp_current_filter[] = $tag; 
  419.  
  420. $args = array(); 
  421. if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this) 
  422. $args[] =& $arg[0]; 
  423. else 
  424. $args[] = $arg; 
  425. for ( $a = 2, $num = func_num_args(); $a < $num; $a++ ) 
  426. $args[] = func_get_arg($a); 
  427.  
  428. $wp_filter[ $tag ]->do_action( $args ); 
  429.  
  430. array_pop($wp_current_filter); 
  431.  
  432. /** 
  433. * Retrieve the number of times an action is fired. 
  434. * 
  435. * @since 2.1.0 
  436. * 
  437. * @global array $wp_actions Increments the amount of times action was triggered. 
  438. * 
  439. * @param string $tag The name of the action hook. 
  440. * @return int The number of times action hook $tag is fired. 
  441. */ 
  442. function did_action($tag) { 
  443. global $wp_actions; 
  444.  
  445. if ( ! isset( $wp_actions[ $tag ] ) ) 
  446. return 0; 
  447.  
  448. return $wp_actions[$tag]; 
  449.  
  450. /** 
  451. * Execute functions hooked on a specific action hook, specifying arguments in an array. 
  452. * 
  453. * @since 2.1.0 
  454. * 
  455. * @see do_action() This function is identical, but the arguments passed to the 
  456. * functions hooked to $tag< are supplied using an array. 
  457. * @global array $wp_filter Stores all of the filters 
  458. * @global array $wp_actions Increments the amount of times action was triggered. 
  459. * @global array $wp_current_filter Stores the list of current filters with the current one last 
  460. * 
  461. * @param string $tag The name of the action to be executed. 
  462. * @param array $args The arguments supplied to the functions hooked to `$tag`. 
  463. */ 
  464. function do_action_ref_array($tag, $args) { 
  465. global $wp_filter, $wp_actions, $wp_current_filter; 
  466.  
  467. if ( ! isset($wp_actions[$tag]) ) 
  468. $wp_actions[$tag] = 1; 
  469. else 
  470. ++$wp_actions[$tag]; 
  471.  
  472. // Do 'all' actions first 
  473. if ( isset($wp_filter['all']) ) { 
  474. $wp_current_filter[] = $tag; 
  475. $all_args = func_get_args(); 
  476. _wp_call_all_hook($all_args); 
  477.  
  478. if ( !isset($wp_filter[$tag]) ) { 
  479. if ( isset($wp_filter['all']) ) 
  480. array_pop($wp_current_filter); 
  481. return; 
  482.  
  483. if ( !isset($wp_filter['all']) ) 
  484. $wp_current_filter[] = $tag; 
  485.  
  486. $wp_filter[ $tag ]->do_action( $args ); 
  487.  
  488. array_pop($wp_current_filter); 
  489.  
  490. /** 
  491. * Check if any action has been registered for a hook. 
  492. * 
  493. * @since 2.5.0 
  494. * 
  495. * @see has_filter() has_action() is an alias of has_filter(). 
  496. * 
  497. * @param string $tag The name of the action hook. 
  498. * @param callable|bool $function_to_check Optional. The callback to check for. Default false. 
  499. * @return bool|int If $function_to_check is omitted, returns boolean for whether the hook has 
  500. * anything registered. When checking a specific function, the priority of that 
  501. * hook is returned, or false if the function is not attached. When using the 
  502. * $function_to_check argument, this function may return a non-boolean value 
  503. * that evaluates to false (e.g.) 0, so use the === operator for testing the 
  504. * return value. 
  505. */ 
  506. function has_action($tag, $function_to_check = false) { 
  507. return has_filter($tag, $function_to_check); 
  508.  
  509. /** 
  510. * Removes a function from a specified action hook. 
  511. * 
  512. * This function removes a function attached to a specified action hook. This 
  513. * method can be used to remove default functions attached to a specific filter 
  514. * hook and possibly replace them with a substitute. 
  515. * 
  516. * @since 1.2.0 
  517. * 
  518. * @param string $tag The action hook to which the function to be removed is hooked. 
  519. * @param callable $function_to_remove The name of the function which should be removed. 
  520. * @param int $priority Optional. The priority of the function. Default 10. 
  521. * @return bool Whether the function is removed. 
  522. */ 
  523. function remove_action( $tag, $function_to_remove, $priority = 10 ) { 
  524. return remove_filter( $tag, $function_to_remove, $priority ); 
  525.  
  526. /** 
  527. * Remove all of the hooks from an action. 
  528. * 
  529. * @since 2.7.0 
  530. * 
  531. * @param string $tag The action to remove hooks from. 
  532. * @param int|bool $priority The priority number to remove them from. Default false. 
  533. * @return true True when finished. 
  534. */ 
  535. function remove_all_actions($tag, $priority = false) { 
  536. return remove_all_filters($tag, $priority); 
  537.  
  538. /** 
  539. * Fires functions attached to a deprecated filter hook. 
  540. * 
  541. * When a filter hook is deprecated, the apply_filters() call is replaced with 
  542. * apply_filters_deprecated(), which triggers a deprecation notice and then fires 
  543. * the original filter hook. 
  544. * 
  545. * @since 4.6.0 
  546. * 
  547. * @see _deprecated_hook() 
  548. * 
  549. * @param string $tag The name of the filter hook. 
  550. * @param array $args Array of additional function arguments to be passed to apply_filters(). 
  551. * @param string $version The version of WordPress that deprecated the hook. 
  552. * @param string $replacement Optional. The hook that should have been used. Default false. 
  553. * @param string $message Optional. A message regarding the change. Default null. 
  554. */ 
  555. function apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) { 
  556. if ( ! has_filter( $tag ) ) { 
  557. return $args[0]; 
  558.  
  559. _deprecated_hook( $tag, $version, $replacement, $message ); 
  560.  
  561. return apply_filters_ref_array( $tag, $args ); 
  562.  
  563. /** 
  564. * Fires functions attached to a deprecated action hook. 
  565. * 
  566. * When an action hook is deprecated, the do_action() call is replaced with 
  567. * do_action_deprecated(), which triggers a deprecation notice and then fires 
  568. * the original hook. 
  569. * 
  570. * @since 4.6.0 
  571. * 
  572. * @see _deprecated_hook() 
  573. * 
  574. * @param string $tag The name of the action hook. 
  575. * @param array $args Array of additional function arguments to be passed to do_action(). 
  576. * @param string $version The version of WordPress that deprecated the hook. 
  577. * @param string $replacement Optional. The hook that should have been used. 
  578. * @param string $message Optional. A message regarding the change. 
  579. */ 
  580. function do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) { 
  581. if ( ! has_action( $tag ) ) { 
  582. return; 
  583.  
  584. _deprecated_hook( $tag, $version, $replacement, $message ); 
  585.  
  586. do_action_ref_array( $tag, $args ); 
  587.  
  588. // 
  589. // Functions for handling plugins. 
  590. // 
  591.   
  592. /** 
  593. * Gets the basename of a plugin. 
  594. * 
  595. * This method extracts the name of a plugin from its filename. 
  596. * 
  597. * @since 1.5.0 
  598. * 
  599. * @global array $wp_plugin_paths 
  600. * 
  601. * @param string $file The filename of plugin. 
  602. * @return string The name of a plugin. 
  603. */ 
  604. function plugin_basename( $file ) { 
  605. global $wp_plugin_paths; 
  606.  
  607. // $wp_plugin_paths contains normalized paths. 
  608. $file = wp_normalize_path( $file ); 
  609.  
  610. arsort( $wp_plugin_paths ); 
  611. foreach ( $wp_plugin_paths as $dir => $realdir ) { 
  612. if ( strpos( $file, $realdir ) === 0 ) { 
  613. $file = $dir . substr( $file, strlen( $realdir ) ); 
  614.  
  615. $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR ); 
  616. $mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR ); 
  617.  
  618. $file = preg_replace('#^' . preg_quote($plugin_dir, '#') . '/|^' . preg_quote($mu_plugin_dir, '#') . '/#', '', $file); // get relative path from plugins dir 
  619. $file = trim($file, '/'); 
  620. return $file; 
  621.  
  622. /** 
  623. * Register a plugin's real path. 
  624. * 
  625. * This is used in plugin_basename() to resolve symlinked paths. 
  626. * 
  627. * @since 3.9.0 
  628. * 
  629. * @see wp_normalize_path() 
  630. * 
  631. * @global array $wp_plugin_paths 
  632. * 
  633. * @staticvar string $wp_plugin_path 
  634. * @staticvar string $wpmu_plugin_path 
  635. * 
  636. * @param string $file Known path to the file. 
  637. * @return bool Whether the path was able to be registered. 
  638. */ 
  639. function wp_register_plugin_realpath( $file ) { 
  640. global $wp_plugin_paths; 
  641.  
  642. // Normalize, but store as static to avoid recalculation of a constant value 
  643. static $wp_plugin_path = null, $wpmu_plugin_path = null; 
  644. if ( ! isset( $wp_plugin_path ) ) { 
  645. $wp_plugin_path = wp_normalize_path( WP_PLUGIN_DIR ); 
  646. $wpmu_plugin_path = wp_normalize_path( WPMU_PLUGIN_DIR ); 
  647.  
  648. $plugin_path = wp_normalize_path( dirname( $file ) ); 
  649. $plugin_realpath = wp_normalize_path( dirname( realpath( $file ) ) ); 
  650.  
  651. if ( $plugin_path === $wp_plugin_path || $plugin_path === $wpmu_plugin_path ) { 
  652. return false; 
  653.  
  654. if ( $plugin_path !== $plugin_realpath ) { 
  655. $wp_plugin_paths[ $plugin_path ] = $plugin_realpath; 
  656.  
  657. return true; 
  658.  
  659. /** 
  660. * Get the filesystem directory path (with trailing slash) for the plugin __FILE__ passed in. 
  661. * 
  662. * @since 2.8.0 
  663. * 
  664. * @param string $file The filename of the plugin (__FILE__). 
  665. * @return string the filesystem path of the directory that contains the plugin. 
  666. */ 
  667. function plugin_dir_path( $file ) { 
  668. return trailingslashit( dirname( $file ) ); 
  669.  
  670. /** 
  671. * Get the URL directory path (with trailing slash) for the plugin __FILE__ passed in. 
  672. * 
  673. * @since 2.8.0 
  674. * 
  675. * @param string $file The filename of the plugin (__FILE__). 
  676. * @return string the URL path of the directory that contains the plugin. 
  677. */ 
  678. function plugin_dir_url( $file ) { 
  679. return trailingslashit( plugins_url( '', $file ) ); 
  680.  
  681. /** 
  682. * Set the activation hook for a plugin. 
  683. * 
  684. * When a plugin is activated, the action 'activate_PLUGINNAME' hook is 
  685. * called. In the name of this hook, PLUGINNAME is replaced with the name 
  686. * of the plugin, including the optional subdirectory. For example, when the 
  687. * plugin is located in wp-content/plugins/sampleplugin/sample.php, then 
  688. * the name of this hook will become 'activate_sampleplugin/sample.php'. 
  689. * 
  690. * When the plugin consists of only one file and is (as by default) located at 
  691. * wp-content/plugins/sample.php the name of this hook will be 
  692. * 'activate_sample.php'. 
  693. * 
  694. * @since 2.0.0 
  695. * 
  696. * @param string $file The filename of the plugin including the path. 
  697. * @param callable $function The function hooked to the 'activate_PLUGIN' action. 
  698. */ 
  699. function register_activation_hook($file, $function) { 
  700. $file = plugin_basename($file); 
  701. add_action('activate_' . $file, $function); 
  702.  
  703. /** 
  704. * Set the deactivation hook for a plugin. 
  705. * 
  706. * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is 
  707. * called. In the name of this hook, PLUGINNAME is replaced with the name 
  708. * of the plugin, including the optional subdirectory. For example, when the 
  709. * plugin is located in wp-content/plugins/sampleplugin/sample.php, then 
  710. * the name of this hook will become 'deactivate_sampleplugin/sample.php'. 
  711. * 
  712. * When the plugin consists of only one file and is (as by default) located at 
  713. * wp-content/plugins/sample.php the name of this hook will be 
  714. * 'deactivate_sample.php'. 
  715. * 
  716. * @since 2.0.0 
  717. * 
  718. * @param string $file The filename of the plugin including the path. 
  719. * @param callable $function The function hooked to the 'deactivate_PLUGIN' action. 
  720. */ 
  721. function register_deactivation_hook($file, $function) { 
  722. $file = plugin_basename($file); 
  723. add_action('deactivate_' . $file, $function); 
  724.  
  725. /** 
  726. * Set the uninstallation hook for a plugin. 
  727. * 
  728. * Registers the uninstall hook that will be called when the user clicks on the 
  729. * uninstall link that calls for the plugin to uninstall itself. The link won't 
  730. * be active unless the plugin hooks into the action. 
  731. * 
  732. * The plugin should not run arbitrary code outside of functions, when 
  733. * registering the uninstall hook. In order to run using the hook, the plugin 
  734. * will have to be included, which means that any code laying outside of a 
  735. * function will be run during the uninstall process. The plugin should not 
  736. * hinder the uninstall process. 
  737. * 
  738. * If the plugin can not be written without running code within the plugin, then 
  739. * the plugin should create a file named 'uninstall.php' in the base plugin 
  740. * folder. This file will be called, if it exists, during the uninstall process 
  741. * bypassing the uninstall hook. The plugin, when using the 'uninstall.php' 
  742. * should always check for the 'WP_UNINSTALL_PLUGIN' constant, before 
  743. * executing. 
  744. * 
  745. * @since 2.7.0 
  746. * 
  747. * @param string $file Plugin file. 
  748. * @param callable $callback The callback to run when the hook is called. Must be 
  749. * a static method or function. 
  750. */ 
  751. function register_uninstall_hook( $file, $callback ) { 
  752. if ( is_array( $callback ) && is_object( $callback[0] ) ) { 
  753. _doing_it_wrong( __FUNCTION__, __( 'Only a static class method or function can be used in an uninstall hook.' ), '3.1.0' ); 
  754. return; 
  755.  
  756. /** 
  757. * The option should not be autoloaded, because it is not needed in most 
  758. * cases. Emphasis should be put on using the 'uninstall.php' way of 
  759. * uninstalling the plugin. 
  760. */ 
  761. $uninstallable_plugins = (array) get_option('uninstall_plugins'); 
  762. $uninstallable_plugins[plugin_basename($file)] = $callback; 
  763.  
  764. update_option('uninstall_plugins', $uninstallable_plugins); 
  765.  
  766. /** 
  767. * Call the 'all' hook, which will process the functions hooked into it. 
  768. * 
  769. * The 'all' hook passes all of the arguments or parameters that were used for 
  770. * the hook, which this function was called for. 
  771. * 
  772. * This function is used internally for apply_filters(), do_action(), and 
  773. * do_action_ref_array() and is not meant to be used from outside those 
  774. * functions. This function does not check for the existence of the all hook, so 
  775. * it will fail unless the all hook exists prior to this function call. 
  776. * 
  777. * @since 2.5.0 
  778. * @access private 
  779. * 
  780. * @global array $wp_filter Stores all of the filters 
  781. * 
  782. * @param array $args The collected parameters from the hook that was called. 
  783. */ 
  784. function _wp_call_all_hook($args) { 
  785. global $wp_filter; 
  786.  
  787. $wp_filter['all']->do_all_hook( $args ); 
  788.  
  789. /** 
  790. * Build Unique ID for storage and retrieval. 
  791. * 
  792. * The old way to serialize the callback caused issues and this function is the 
  793. * solution. It works by checking for objects and creating a new property in 
  794. * the class to keep track of the object and new objects of the same class that 
  795. * need to be added. 
  796. * 
  797. * It also allows for the removal of actions and filters for objects after they 
  798. * change class properties. It is possible to include the property $wp_filter_id 
  799. * in your class and set it to "null" or a number to bypass the workaround. 
  800. * However this will prevent you from adding new classes and any new classes 
  801. * will overwrite the previous hook by the same class. 
  802. * 
  803. * Functions and static method callbacks are just returned as strings and 
  804. * shouldn't have any speed penalty. 
  805. * 
  806. * @link https://core.trac.wordpress.org/ticket/3875 
  807. * 
  808. * @since 2.2.3 
  809. * @access private 
  810. * 
  811. * @global array $wp_filter Storage for all of the filters and actions. 
  812. * @staticvar int $filter_id_count 
  813. * 
  814. * @param string $tag Used in counting how many hooks were applied 
  815. * @param callable $function Used for creating unique id 
  816. * @param int|bool $priority Used in counting how many hooks were applied. If === false 
  817. * and $function is an object reference, we return the unique 
  818. * id only if it already has one, false otherwise. 
  819. * @return string|false Unique ID for usage as array key or false if $priority === false 
  820. * and $function is an object reference, and it does not already have 
  821. * a unique id. 
  822. */ 
  823. function _wp_filter_build_unique_id($tag, $function, $priority) { 
  824. global $wp_filter; 
  825. static $filter_id_count = 0; 
  826.  
  827. if ( is_string($function) ) 
  828. return $function; 
  829.  
  830. if ( is_object($function) ) { 
  831. // Closures are currently implemented as objects 
  832. $function = array( $function, '' ); 
  833. } else { 
  834. $function = (array) $function; 
  835.  
  836. if (is_object($function[0]) ) { 
  837. // Object Class Calling 
  838. if ( function_exists('spl_object_hash') ) { 
  839. return spl_object_hash($function[0]) . $function[1]; 
  840. } else { 
  841. $obj_idx = get_class($function[0]).$function[1]; 
  842. if ( !isset($function[0]->wp_filter_id) ) { 
  843. if ( false === $priority ) 
  844. return false; 
  845. $obj_idx .= isset($wp_filter[$tag][$priority]) ? count((array)$wp_filter[$tag][$priority]) : $filter_id_count; 
  846. $function[0]->wp_filter_id = $filter_id_count; 
  847. ++$filter_id_count; 
  848. } else { 
  849. $obj_idx .= $function[0]->wp_filter_id; 
  850.  
  851. return $obj_idx; 
  852. } elseif ( is_string( $function[0] ) ) { 
  853. // Static Calling 
  854. return $function[0] . '::' . $function[1]; 
.