Hooks.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. /**
  3. * Hooks.php -- a tool for running hook functions
  4. * Copyright 2004, 2005 Evan Prodromou <evan@wikitravel.org>.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  19. *
  20. * @author Evan Prodromou <evan@wikitravel.org>
  21. * @see hooks.txt
  22. * @file
  23. */
  24. /**
  25. * Because programmers assign to $wgHooks, we need to be very
  26. * careful about its contents. So, there's a lot more error-checking
  27. * in here than would normally be necessary.
  28. */
  29. function wfRunHooks($event, $args = array()) {
  30. global $wgHooks;
  31. if (!is_array($wgHooks)) {
  32. throw new MWException("Global hooks array is not an array!\n");
  33. return false;
  34. }
  35. if (!array_key_exists($event, $wgHooks)) {
  36. return true;
  37. }
  38. if (!is_array($wgHooks[$event])) {
  39. throw new MWException("Hooks array for event '$event' is not an array!\n");
  40. return false;
  41. }
  42. foreach ($wgHooks[$event] as $index => $hook) {
  43. $object = NULL;
  44. $method = NULL;
  45. $func = NULL;
  46. $data = NULL;
  47. $have_data = false;
  48. /* $hook can be: a function, an object, an array of $function and $data,
  49. * an array of just a function, an array of object and method, or an
  50. * array of object, method, and data.
  51. */
  52. if (is_array($hook)) {
  53. if (count($hook) < 1) {
  54. throw new MWException("Empty array in hooks for " . $event . "\n");
  55. } else if (is_object($hook[0])) {
  56. $object = $wgHooks[$event][$index][0];
  57. if (count($hook) < 2) {
  58. $method = "on" . $event;
  59. } else {
  60. $method = $hook[1];
  61. if (count($hook) > 2) {
  62. $data = $hook[2];
  63. $have_data = true;
  64. }
  65. }
  66. } else if (is_string($hook[0])) {
  67. $func = $hook[0];
  68. if (count($hook) > 1) {
  69. $data = $hook[1];
  70. $have_data = true;
  71. }
  72. } else {
  73. var_dump( $wgHooks );
  74. throw new MWException("Unknown datatype in hooks for " . $event . "\n");
  75. }
  76. } else if (is_string($hook)) { # functions look like strings, too
  77. $func = $hook;
  78. } else if (is_object($hook)) {
  79. $object = $wgHooks[$event][$index];
  80. $method = "on" . $event;
  81. } else {
  82. throw new MWException("Unknown datatype in hooks for " . $event . "\n");
  83. }
  84. /* We put the first data element on, if needed. */
  85. if ($have_data) {
  86. $hook_args = array_merge(array($data), $args);
  87. } else {
  88. $hook_args = $args;
  89. }
  90. if ( isset( $object ) ) {
  91. $func = get_class( $object ) . '::' . $method;
  92. $callback = array( $object, $method );
  93. } elseif ( false !== ( $pos = strpos( $func, '::' ) ) ) {
  94. $callback = array( substr( $func, 0, $pos ), substr( $func, $pos + 2 ) );
  95. } else {
  96. $callback = $func;
  97. }
  98. // Run autoloader (workaround for call_user_func_array bug)
  99. is_callable( $callback );
  100. /* Call the hook. */
  101. wfProfileIn( $func );
  102. $retval = call_user_func_array( $callback, $hook_args );
  103. wfProfileOut( $func );
  104. /* String return is an error; false return means stop processing. */
  105. if (is_string($retval)) {
  106. global $wgOut;
  107. $wgOut->showFatalError($retval);
  108. return false;
  109. } elseif( $retval === null ) {
  110. if( is_array( $callback ) ) {
  111. if( is_object( $callback[0] ) ) {
  112. $prettyClass = get_class( $callback[0] );
  113. } else {
  114. $prettyClass = strval( $callback[0] );
  115. }
  116. $prettyFunc = $prettyClass . '::' . strval( $callback[1] );
  117. } else {
  118. $prettyFunc = strval( $callback );
  119. }
  120. throw new MWException( "Detected bug in an extension! " .
  121. "Hook $prettyFunc failed to return a value; " .
  122. "should return true to continue hook processing or false to abort." );
  123. } else if (!$retval) {
  124. return false;
  125. }
  126. }
  127. return true;
  128. }