PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/plugin.php

https://bitbucket.org/julianelve/vendor-wordpress
PHP | 789 lines | 269 code | 84 blank | 436 comment | 67 complexity | 49eff254c204787164d1a2ca8437ad71 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.1, GPL-2.0
  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 http://us2.php.net/manual/en/language.pseudo-types.php#language.types.callback 'callback'}
  12. * type are valid.
  13. *
  14. * Also see the {@link http://codex.wordpress.org/Plugin_API Plugin API} for
  15. * more information and examples on how to use a lot of these functions.
  16. *
  17. * @package WordPress
  18. * @subpackage Plugin
  19. * @since 1.5
  20. */
  21. /**
  22. * Hooks a function or method to a specific filter action.
  23. *
  24. * Filters are the hooks that WordPress launches to modify text of various types
  25. * before adding it to the database or sending it to the browser screen. Plugins
  26. * can specify that one or more of its PHP functions is executed to
  27. * modify specific types of text at these times, using the Filter API.
  28. *
  29. * To use the API, the following code should be used to bind a callback to the
  30. * filter.
  31. *
  32. * <code>
  33. * function example_hook($example) { echo $example; }
  34. * add_filter('example_filter', 'example_hook');
  35. * </code>
  36. *
  37. * In WordPress 1.5.1+, hooked functions can take extra arguments that are set
  38. * when the matching do_action() or apply_filters() call is run. The
  39. * $accepted_args allow for calling functions only when the number of args
  40. * match. Hooked functions can take extra arguments that are set when the
  41. * matching do_action() or apply_filters() call is run. For example, the action
  42. * comment_id_not_found will pass any functions that hook onto it the ID of the
  43. * requested comment.
  44. *
  45. * <strong>Note:</strong> the function will return true no matter if the
  46. * function was hooked fails or not. There are no checks for whether the
  47. * function exists beforehand and no checks to whether the <tt>$function_to_add
  48. * is even a string. It is up to you to take care and this is done for
  49. * optimization purposes, so everything is as quick as possible.
  50. *
  51. * @package WordPress
  52. * @subpackage Plugin
  53. * @since 0.71
  54. * @global array $wp_filter Stores all of the filters added in the form of
  55. * wp_filter['tag']['array of priorities']['array of functions serialized']['array of ['array (functions, accepted_args)']']
  56. * @global array $merged_filters Tracks the tags that need to be merged for later. If the hook is added, it doesn't need to run through that process.
  57. *
  58. * @param string $tag The name of the filter to hook the $function_to_add to.
  59. * @param callback $function_to_add The name of the function to be called when the filter is applied.
  60. * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action.
  61. * @param int $accepted_args optional. The number of arguments the function accept (default 1).
  62. * @return boolean true
  63. */
  64. function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
  65. global $wp_filter, $merged_filters;
  66. $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
  67. $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
  68. unset( $merged_filters[ $tag ] );
  69. return true;
  70. }
  71. /**
  72. * Check if any filter has been registered for a hook.
  73. *
  74. * @package WordPress
  75. * @subpackage Plugin
  76. * @since 2.5
  77. * @global array $wp_filter Stores all of the filters
  78. *
  79. * @param string $tag The name of the filter hook.
  80. * @param callback $function_to_check optional.
  81. * @return mixed If $function_to_check is omitted, returns boolean for whether the hook has anything registered.
  82. * When checking a specific function, the priority of that hook is returned, or false if the function is not attached.
  83. * When using the $function_to_check argument, this function may return a non-boolean value that evaluates to false
  84. * (e.g.) 0, so use the === operator for testing the return value.
  85. */
  86. function has_filter($tag, $function_to_check = false) {
  87. global $wp_filter;
  88. $has = !empty($wp_filter[$tag]);
  89. if ( false === $function_to_check || false == $has )
  90. return $has;
  91. if ( !$idx = _wp_filter_build_unique_id($tag, $function_to_check, false) )
  92. return false;
  93. foreach ( (array) array_keys($wp_filter[$tag]) as $priority ) {
  94. if ( isset($wp_filter[$tag][$priority][$idx]) )
  95. return $priority;
  96. }
  97. return false;
  98. }
  99. /**
  100. * Call the functions added to a filter hook.
  101. *
  102. * The callback functions attached to filter hook $tag are invoked by calling
  103. * this function. This function can be used to create a new filter hook by
  104. * simply calling this function with the name of the new hook specified using
  105. * the $tag parameter.
  106. *
  107. * The function allows for additional arguments to be added and passed to hooks.
  108. * <code>
  109. * function example_hook($string, $arg1, $arg2)
  110. * {
  111. * //Do stuff
  112. * return $string;
  113. * }
  114. * $value = apply_filters('example_filter', 'filter me', 'arg1', 'arg2');
  115. * </code>
  116. *
  117. * @package WordPress
  118. * @subpackage Plugin
  119. * @since 0.71
  120. * @global array $wp_filter Stores all of the filters
  121. * @global array $merged_filters Merges the filter hooks using this function.
  122. * @global array $wp_current_filter stores the list of current filters with the current one last
  123. *
  124. * @param string $tag The name of the filter hook.
  125. * @param mixed $value The value on which the filters hooked to <tt>$tag</tt> are applied on.
  126. * @param mixed $var,... Additional variables passed to the functions hooked to <tt>$tag</tt>.
  127. * @return mixed The filtered value after all hooked functions are applied to it.
  128. */
  129. function apply_filters($tag, $value) {
  130. global $wp_filter, $merged_filters, $wp_current_filter;
  131. $args = array();
  132. // Do 'all' actions first
  133. if ( isset($wp_filter['all']) ) {
  134. $wp_current_filter[] = $tag;
  135. $args = func_get_args();
  136. _wp_call_all_hook($args);
  137. }
  138. if ( !isset($wp_filter[$tag]) ) {
  139. if ( isset($wp_filter['all']) )
  140. array_pop($wp_current_filter);
  141. return $value;
  142. }
  143. if ( !isset($wp_filter['all']) )
  144. $wp_current_filter[] = $tag;
  145. // Sort
  146. if ( !isset( $merged_filters[ $tag ] ) ) {
  147. ksort($wp_filter[$tag]);
  148. $merged_filters[ $tag ] = true;
  149. }
  150. reset( $wp_filter[ $tag ] );
  151. if ( empty($args) )
  152. $args = func_get_args();
  153. do {
  154. foreach( (array) current($wp_filter[$tag]) as $the_ )
  155. if ( !is_null($the_['function']) ){
  156. $args[1] = $value;
  157. $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
  158. }
  159. } while ( next($wp_filter[$tag]) !== false );
  160. array_pop( $wp_current_filter );
  161. return $value;
  162. }
  163. /**
  164. * Execute functions hooked on a specific filter hook, specifying arguments in an array.
  165. *
  166. * @see apply_filters() This function is identical, but the arguments passed to the
  167. * functions hooked to <tt>$tag</tt> are supplied using an array.
  168. *
  169. * @package WordPress
  170. * @subpackage Plugin
  171. * @since 3.0.0
  172. * @global array $wp_filter Stores all of the filters
  173. * @global array $merged_filters Merges the filter hooks using this function.
  174. * @global array $wp_current_filter stores the list of current filters with the current one last
  175. *
  176. * @param string $tag The name of the filter hook.
  177. * @param array $args The arguments supplied to the functions hooked to <tt>$tag</tt>
  178. * @return mixed The filtered value after all hooked functions are applied to it.
  179. */
  180. function apply_filters_ref_array($tag, $args) {
  181. global $wp_filter, $merged_filters, $wp_current_filter;
  182. // Do 'all' actions first
  183. if ( isset($wp_filter['all']) ) {
  184. $wp_current_filter[] = $tag;
  185. $all_args = func_get_args();
  186. _wp_call_all_hook($all_args);
  187. }
  188. if ( !isset($wp_filter[$tag]) ) {
  189. if ( isset($wp_filter['all']) )
  190. array_pop($wp_current_filter);
  191. return $args[0];
  192. }
  193. if ( !isset($wp_filter['all']) )
  194. $wp_current_filter[] = $tag;
  195. // Sort
  196. if ( !isset( $merged_filters[ $tag ] ) ) {
  197. ksort($wp_filter[$tag]);
  198. $merged_filters[ $tag ] = true;
  199. }
  200. reset( $wp_filter[ $tag ] );
  201. do {
  202. foreach( (array) current($wp_filter[$tag]) as $the_ )
  203. if ( !is_null($the_['function']) )
  204. $args[0] = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
  205. } while ( next($wp_filter[$tag]) !== false );
  206. array_pop( $wp_current_filter );
  207. return $args[0];
  208. }
  209. /**
  210. * Removes a function from a specified filter hook.
  211. *
  212. * This function removes a function attached to a specified filter hook. This
  213. * method can be used to remove default functions attached to a specific filter
  214. * hook and possibly replace them with a substitute.
  215. *
  216. * To remove a hook, the $function_to_remove and $priority arguments must match
  217. * when the hook was added. This goes for both filters and actions. No warning
  218. * will be given on removal failure.
  219. *
  220. * @package WordPress
  221. * @subpackage Plugin
  222. * @since 1.2
  223. *
  224. * @param string $tag The filter hook to which the function to be removed is hooked.
  225. * @param callback $function_to_remove The name of the function which should be removed.
  226. * @param int $priority optional. The priority of the function (default: 10).
  227. * @param int $accepted_args optional. The number of arguments the function accepts (default: 1).
  228. * @return boolean Whether the function existed before it was removed.
  229. */
  230. function remove_filter( $tag, $function_to_remove, $priority = 10 ) {
  231. $function_to_remove = _wp_filter_build_unique_id($tag, $function_to_remove, $priority);
  232. $r = isset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]);
  233. if ( true === $r) {
  234. unset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]);
  235. if ( empty($GLOBALS['wp_filter'][$tag][$priority]) )
  236. unset($GLOBALS['wp_filter'][$tag][$priority]);
  237. unset($GLOBALS['merged_filters'][$tag]);
  238. }
  239. return $r;
  240. }
  241. /**
  242. * Remove all of the hooks from a filter.
  243. *
  244. * @since 2.7
  245. *
  246. * @param string $tag The filter to remove hooks from.
  247. * @param int $priority The priority number to remove.
  248. * @return bool True when finished.
  249. */
  250. function remove_all_filters($tag, $priority = false) {
  251. global $wp_filter, $merged_filters;
  252. if( isset($wp_filter[$tag]) ) {
  253. if( false !== $priority && isset($wp_filter[$tag][$priority]) )
  254. unset($wp_filter[$tag][$priority]);
  255. else
  256. unset($wp_filter[$tag]);
  257. }
  258. if( isset($merged_filters[$tag]) )
  259. unset($merged_filters[$tag]);
  260. return true;
  261. }
  262. /**
  263. * Retrieve the name of the current filter or action.
  264. *
  265. * @package WordPress
  266. * @subpackage Plugin
  267. * @since 2.5
  268. *
  269. * @return string Hook name of the current filter or action.
  270. */
  271. function current_filter() {
  272. global $wp_current_filter;
  273. return end( $wp_current_filter );
  274. }
  275. /**
  276. * Hooks a function on to a specific action.
  277. *
  278. * Actions are the hooks that the WordPress core launches at specific points
  279. * during execution, or when specific events occur. Plugins can specify that
  280. * one or more of its PHP functions are executed at these points, using the
  281. * Action API.
  282. *
  283. * @uses add_filter() Adds an action. Parameter list and functionality are the same.
  284. *
  285. * @package WordPress
  286. * @subpackage Plugin
  287. * @since 1.2
  288. *
  289. * @param string $tag The name of the action to which the $function_to_add is hooked.
  290. * @param callback $function_to_add The name of the function you wish to be called.
  291. * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action.
  292. * @param int $accepted_args optional. The number of arguments the function accept (default 1).
  293. */
  294. function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
  295. return add_filter($tag, $function_to_add, $priority, $accepted_args);
  296. }
  297. /**
  298. * Execute functions hooked on a specific action hook.
  299. *
  300. * This function invokes all functions attached to action hook $tag. It is
  301. * possible to create new action hooks by simply calling this function,
  302. * specifying the name of the new hook using the <tt>$tag</tt> parameter.
  303. *
  304. * You can pass extra arguments to the hooks, much like you can with
  305. * apply_filters().
  306. *
  307. * @see apply_filters() This function works similar with the exception that
  308. * nothing is returned and only the functions or methods are called.
  309. *
  310. * @package WordPress
  311. * @subpackage Plugin
  312. * @since 1.2
  313. * @global array $wp_filter Stores all of the filters
  314. * @global array $wp_actions Increments the amount of times action was triggered.
  315. *
  316. * @param string $tag The name of the action to be executed.
  317. * @param mixed $arg,... Optional additional arguments which are passed on to the functions hooked to the action.
  318. * @return null Will return null if $tag does not exist in $wp_filter array
  319. */
  320. function do_action($tag, $arg = '') {
  321. global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
  322. if ( ! isset($wp_actions) )
  323. $wp_actions = array();
  324. if ( ! isset($wp_actions[$tag]) )
  325. $wp_actions[$tag] = 1;
  326. else
  327. ++$wp_actions[$tag];
  328. // Do 'all' actions first
  329. if ( isset($wp_filter['all']) ) {
  330. $wp_current_filter[] = $tag;
  331. $all_args = func_get_args();
  332. _wp_call_all_hook($all_args);
  333. }
  334. if ( !isset($wp_filter[$tag]) ) {
  335. if ( isset($wp_filter['all']) )
  336. array_pop($wp_current_filter);
  337. return;
  338. }
  339. if ( !isset($wp_filter['all']) )
  340. $wp_current_filter[] = $tag;
  341. $args = array();
  342. if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
  343. $args[] =& $arg[0];
  344. else
  345. $args[] = $arg;
  346. for ( $a = 2; $a < func_num_args(); $a++ )
  347. $args[] = func_get_arg($a);
  348. // Sort
  349. if ( !isset( $merged_filters[ $tag ] ) ) {
  350. ksort($wp_filter[$tag]);
  351. $merged_filters[ $tag ] = true;
  352. }
  353. reset( $wp_filter[ $tag ] );
  354. do {
  355. foreach ( (array) current($wp_filter[$tag]) as $the_ )
  356. if ( !is_null($the_['function']) )
  357. call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
  358. } while ( next($wp_filter[$tag]) !== false );
  359. array_pop($wp_current_filter);
  360. }
  361. /**
  362. * Retrieve the number of times an action is fired.
  363. *
  364. * @package WordPress
  365. * @subpackage Plugin
  366. * @since 2.1
  367. * @global array $wp_actions Increments the amount of times action was triggered.
  368. *
  369. * @param string $tag The name of the action hook.
  370. * @return int The number of times action hook <tt>$tag</tt> is fired
  371. */
  372. function did_action($tag) {
  373. global $wp_actions;
  374. if ( ! isset( $wp_actions ) || ! isset( $wp_actions[$tag] ) )
  375. return 0;
  376. return $wp_actions[$tag];
  377. }
  378. /**
  379. * Execute functions hooked on a specific action hook, specifying arguments in an array.
  380. *
  381. * @see do_action() This function is identical, but the arguments passed to the
  382. * functions hooked to <tt>$tag</tt> are supplied using an array.
  383. *
  384. * @package WordPress
  385. * @subpackage Plugin
  386. * @since 2.1
  387. * @global array $wp_filter Stores all of the filters
  388. * @global array $wp_actions Increments the amount of times action was triggered.
  389. *
  390. * @param string $tag The name of the action to be executed.
  391. * @param array $args The arguments supplied to the functions hooked to <tt>$tag</tt>
  392. * @return null Will return null if $tag does not exist in $wp_filter array
  393. */
  394. function do_action_ref_array($tag, $args) {
  395. global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
  396. if ( ! isset($wp_actions) )
  397. $wp_actions = array();
  398. if ( ! isset($wp_actions[$tag]) )
  399. $wp_actions[$tag] = 1;
  400. else
  401. ++$wp_actions[$tag];
  402. // Do 'all' actions first
  403. if ( isset($wp_filter['all']) ) {
  404. $wp_current_filter[] = $tag;
  405. $all_args = func_get_args();
  406. _wp_call_all_hook($all_args);
  407. }
  408. if ( !isset($wp_filter[$tag]) ) {
  409. if ( isset($wp_filter['all']) )
  410. array_pop($wp_current_filter);
  411. return;
  412. }
  413. if ( !isset($wp_filter['all']) )
  414. $wp_current_filter[] = $tag;
  415. // Sort
  416. if ( !isset( $merged_filters[ $tag ] ) ) {
  417. ksort($wp_filter[$tag]);
  418. $merged_filters[ $tag ] = true;
  419. }
  420. reset( $wp_filter[ $tag ] );
  421. do {
  422. foreach( (array) current($wp_filter[$tag]) as $the_ )
  423. if ( !is_null($the_['function']) )
  424. call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
  425. } while ( next($wp_filter[$tag]) !== false );
  426. array_pop($wp_current_filter);
  427. }
  428. /**
  429. * Check if any action has been registered for a hook.
  430. *
  431. * @package WordPress
  432. * @subpackage Plugin
  433. * @since 2.5
  434. * @see has_filter() has_action() is an alias of has_filter().
  435. *
  436. * @param string $tag The name of the action hook.
  437. * @param callback $function_to_check optional.
  438. * @return mixed If $function_to_check is omitted, returns boolean for whether the hook has anything registered.
  439. * When checking a specific function, the priority of that hook is returned, or false if the function is not attached.
  440. * When using the $function_to_check argument, this function may return a non-boolean value that evaluates to false
  441. * (e.g.) 0, so use the === operator for testing the return value.
  442. */
  443. function has_action($tag, $function_to_check = false) {
  444. return has_filter($tag, $function_to_check);
  445. }
  446. /**
  447. * Removes a function from a specified action hook.
  448. *
  449. * This function removes a function attached to a specified action hook. This
  450. * method can be used to remove default functions attached to a specific filter
  451. * hook and possibly replace them with a substitute.
  452. *
  453. * @package WordPress
  454. * @subpackage Plugin
  455. * @since 1.2
  456. *
  457. * @param string $tag The action hook to which the function to be removed is hooked.
  458. * @param callback $function_to_remove The name of the function which should be removed.
  459. * @param int $priority optional The priority of the function (default: 10).
  460. * @return boolean Whether the function is removed.
  461. */
  462. function remove_action( $tag, $function_to_remove, $priority = 10 ) {
  463. return remove_filter( $tag, $function_to_remove, $priority );
  464. }
  465. /**
  466. * Remove all of the hooks from an action.
  467. *
  468. * @since 2.7
  469. *
  470. * @param string $tag The action to remove hooks from.
  471. * @param int $priority The priority number to remove them from.
  472. * @return bool True when finished.
  473. */
  474. function remove_all_actions($tag, $priority = false) {
  475. return remove_all_filters($tag, $priority);
  476. }
  477. //
  478. // Functions for handling plugins.
  479. //
  480. /**
  481. * Gets the basename of a plugin.
  482. *
  483. * This method extracts the name of a plugin from its filename.
  484. *
  485. * @package WordPress
  486. * @subpackage Plugin
  487. * @since 1.5
  488. *
  489. * @access private
  490. *
  491. * @param string $file The filename of plugin.
  492. * @return string The name of a plugin.
  493. * @uses WP_PLUGIN_DIR
  494. */
  495. function plugin_basename($file) {
  496. $file = str_replace('\\','/',$file); // sanitize for Win32 installs
  497. $file = preg_replace('|/+|','/', $file); // remove any duplicate slash
  498. $plugin_dir = str_replace('\\','/',WP_PLUGIN_DIR); // sanitize for Win32 installs
  499. $plugin_dir = preg_replace('|/+|','/', $plugin_dir); // remove any duplicate slash
  500. $mu_plugin_dir = str_replace('\\','/',WPMU_PLUGIN_DIR); // sanitize for Win32 installs
  501. $mu_plugin_dir = preg_replace('|/+|','/', $mu_plugin_dir); // remove any duplicate slash
  502. $file = preg_replace('#^' . preg_quote($plugin_dir, '#') . '/|^' . preg_quote($mu_plugin_dir, '#') . '/#','',$file); // get relative path from plugins dir
  503. $file = trim($file, '/');
  504. return $file;
  505. }
  506. /**
  507. * Gets the filesystem directory path (with trailing slash) for the plugin __FILE__ passed in
  508. * @package WordPress
  509. * @subpackage Plugin
  510. * @since 2.8
  511. *
  512. * @param string $file The filename of the plugin (__FILE__)
  513. * @return string the filesystem path of the directory that contains the plugin
  514. */
  515. function plugin_dir_path( $file ) {
  516. return trailingslashit( dirname( $file ) );
  517. }
  518. /**
  519. * Gets the URL directory path (with trailing slash) for the plugin __FILE__ passed in
  520. * @package WordPress
  521. * @subpackage Plugin
  522. * @since 2.8
  523. *
  524. * @param string $file The filename of the plugin (__FILE__)
  525. * @return string the URL path of the directory that contains the plugin
  526. */
  527. function plugin_dir_url( $file ) {
  528. return trailingslashit( plugins_url( '', $file ) );
  529. }
  530. /**
  531. * Set the activation hook for a plugin.
  532. *
  533. * When a plugin is activated, the action 'activate_PLUGINNAME' hook is
  534. * activated. In the name of this hook, PLUGINNAME is replaced with the name of
  535. * the plugin, including the optional subdirectory. For example, when the plugin
  536. * is located in wp-content/plugin/sampleplugin/sample.php, then the name of
  537. * this hook will become 'activate_sampleplugin/sample.php'. When the plugin
  538. * consists of only one file and is (as by default) located at
  539. * wp-content/plugin/sample.php the name of this hook will be
  540. * 'activate_sample.php'.
  541. *
  542. * @package WordPress
  543. * @subpackage Plugin
  544. * @since 2.0
  545. *
  546. * @param string $file The filename of the plugin including the path.
  547. * @param callback $function the function hooked to the 'activate_PLUGIN' action.
  548. */
  549. function register_activation_hook($file, $function) {
  550. $file = plugin_basename($file);
  551. add_action('activate_' . $file, $function);
  552. }
  553. /**
  554. * Set the deactivation hook for a plugin.
  555. *
  556. * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is
  557. * deactivated. In the name of this hook, PLUGINNAME is replaced with the name
  558. * of the plugin, including the optional subdirectory. For example, when the
  559. * plugin is located in wp-content/plugin/sampleplugin/sample.php, then
  560. * the name of this hook will become 'activate_sampleplugin/sample.php'.
  561. *
  562. * When the plugin consists of only one file and is (as by default) located at
  563. * wp-content/plugin/sample.php the name of this hook will be
  564. * 'activate_sample.php'.
  565. *
  566. * @package WordPress
  567. * @subpackage Plugin
  568. * @since 2.0
  569. *
  570. * @param string $file The filename of the plugin including the path.
  571. * @param callback $function the function hooked to the 'activate_PLUGIN' action.
  572. */
  573. function register_deactivation_hook($file, $function) {
  574. $file = plugin_basename($file);
  575. add_action('deactivate_' . $file, $function);
  576. }
  577. /**
  578. * Set the uninstallation hook for a plugin.
  579. *
  580. * Registers the uninstall hook that will be called when the user clicks on the
  581. * uninstall link that calls for the plugin to uninstall itself. The link won't
  582. * be active unless the plugin hooks into the action.
  583. *
  584. * The plugin should not run arbitrary code outside of functions, when
  585. * registering the uninstall hook. In order to run using the hook, the plugin
  586. * will have to be included, which means that any code laying outside of a
  587. * function will be run during the uninstall process. The plugin should not
  588. * hinder the uninstall process.
  589. *
  590. * If the plugin can not be written without running code within the plugin, then
  591. * the plugin should create a file named 'uninstall.php' in the base plugin
  592. * folder. This file will be called, if it exists, during the uninstall process
  593. * bypassing the uninstall hook. The plugin, when using the 'uninstall.php'
  594. * should always check for the 'WP_UNINSTALL_PLUGIN' constant, before
  595. * executing.
  596. *
  597. * @since 2.7
  598. *
  599. * @param string $file
  600. * @param callback $callback The callback to run when the hook is called. Must be a static method or function.
  601. */
  602. function register_uninstall_hook( $file, $callback ) {
  603. if ( is_array( $callback ) && is_object( $callback[0] ) ) {
  604. _doing_it_wrong( __FUNCTION__, __( 'Only a static class method or function can be used in an uninstall hook.' ), '3.1' );
  605. return;
  606. }
  607. // The option should not be autoloaded, because it is not needed in most
  608. // cases. Emphasis should be put on using the 'uninstall.php' way of
  609. // uninstalling the plugin.
  610. $uninstallable_plugins = (array) get_option('uninstall_plugins');
  611. $uninstallable_plugins[plugin_basename($file)] = $callback;
  612. update_option('uninstall_plugins', $uninstallable_plugins);
  613. }
  614. /**
  615. * Calls the 'all' hook, which will process the functions hooked into it.
  616. *
  617. * The 'all' hook passes all of the arguments or parameters that were used for
  618. * the hook, which this function was called for.
  619. *
  620. * This function is used internally for apply_filters(), do_action(), and
  621. * do_action_ref_array() and is not meant to be used from outside those
  622. * functions. This function does not check for the existence of the all hook, so
  623. * it will fail unless the all hook exists prior to this function call.
  624. *
  625. * @package WordPress
  626. * @subpackage Plugin
  627. * @since 2.5
  628. * @access private
  629. *
  630. * @uses $wp_filter Used to process all of the functions in the 'all' hook
  631. *
  632. * @param array $args The collected parameters from the hook that was called.
  633. * @param string $hook Optional. The hook name that was used to call the 'all' hook.
  634. */
  635. function _wp_call_all_hook($args) {
  636. global $wp_filter;
  637. reset( $wp_filter['all'] );
  638. do {
  639. foreach( (array) current($wp_filter['all']) as $the_ )
  640. if ( !is_null($the_['function']) )
  641. call_user_func_array($the_['function'], $args);
  642. } while ( next($wp_filter['all']) !== false );
  643. }
  644. /**
  645. * Build Unique ID for storage and retrieval.
  646. *
  647. * The old way to serialize the callback caused issues and this function is the
  648. * solution. It works by checking for objects and creating an a new property in
  649. * the class to keep track of the object and new objects of the same class that
  650. * need to be added.
  651. *
  652. * It also allows for the removal of actions and filters for objects after they
  653. * change class properties. It is possible to include the property $wp_filter_id
  654. * in your class and set it to "null" or a number to bypass the workaround.
  655. * However this will prevent you from adding new classes and any new classes
  656. * will overwrite the previous hook by the same class.
  657. *
  658. * Functions and static method callbacks are just returned as strings and
  659. * shouldn't have any speed penalty.
  660. *
  661. * @package WordPress
  662. * @subpackage Plugin
  663. * @access private
  664. * @since 2.2.3
  665. * @link http://trac.wordpress.org/ticket/3875
  666. *
  667. * @global array $wp_filter Storage for all of the filters and actions
  668. * @param string $tag Used in counting how many hooks were applied
  669. * @param callback $function Used for creating unique id
  670. * @param int|bool $priority Used in counting how many hooks were applied. If === false and $function is an object reference, we return the unique id only if it already has one, false otherwise.
  671. * @return string|bool Unique ID for usage as array key or false if $priority === false and $function is an object reference, and it does not already have a unique id.
  672. */
  673. function _wp_filter_build_unique_id($tag, $function, $priority) {
  674. global $wp_filter;
  675. static $filter_id_count = 0;
  676. if ( is_string($function) )
  677. return $function;
  678. if ( is_object($function) ) {
  679. // Closures are currently implemented as objects
  680. $function = array( $function, '' );
  681. } else {
  682. $function = (array) $function;
  683. }
  684. if (is_object($function[0]) ) {
  685. // Object Class Calling
  686. if ( function_exists('spl_object_hash') ) {
  687. return spl_object_hash($function[0]) . $function[1];
  688. } else {
  689. $obj_idx = get_class($function[0]).$function[1];
  690. if ( !isset($function[0]->wp_filter_id) ) {
  691. if ( false === $priority )
  692. return false;
  693. $obj_idx .= isset($wp_filter[$tag][$priority]) ? count((array)$wp_filter[$tag][$priority]) : $filter_id_count;
  694. $function[0]->wp_filter_id = $filter_id_count;
  695. ++$filter_id_count;
  696. } else {
  697. $obj_idx .= $function[0]->wp_filter_id;
  698. }
  699. return $obj_idx;
  700. }
  701. } else if ( is_string($function[0]) ) {
  702. // Static Calling
  703. return $function[0].$function[1];
  704. }
  705. }