pluggable.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. <?php
  2. /**
  3. * @group pluggable
  4. */
  5. class Tests_Pluggable extends WP_UnitTestCase {
  6. /**
  7. * Tests that the signatures of all functions in pluggable.php match their expected signature.
  8. *
  9. * @ticket 33654
  10. * @ticket 33867
  11. *
  12. * @dataProvider get_defined_pluggable_functions
  13. */
  14. public function test_pluggable_function_signatures_match( $function ) {
  15. $signatures = $this->get_pluggable_function_signatures();
  16. $this->assertTrue( function_exists( $function ) );
  17. $this->assertArrayHasKey( $function, $signatures );
  18. $function_ref = new ReflectionFunction( $function );
  19. $param_refs = $function_ref->getParameters();
  20. $this->assertSame( count( $signatures[ $function ] ), count( $param_refs ) );
  21. $i = 0;
  22. foreach ( $signatures[ $function ] as $name => $value ) {
  23. $param_ref = $param_refs[ $i ];
  24. $msg = 'Parameter: ' . $param_ref->getName();
  25. if ( is_numeric( $name ) ) {
  26. $name = $value;
  27. $this->assertFalse( $param_ref->isOptional(), $msg );
  28. } else {
  29. $this->assertTrue( $param_ref->isOptional(), $msg );
  30. $this->assertSame( $value, $param_ref->getDefaultValue(), $msg );
  31. }
  32. $this->assertSame( $name, $param_ref->getName(), $msg );
  33. $i++;
  34. }
  35. }
  36. /**
  37. * Test the tests. Makes sure all the expected pluggable functions exist and that they live in pluggable.php.
  38. *
  39. * @ticket 33654
  40. * @ticket 33867
  41. */
  42. public function test_all_pluggable_functions_exist() {
  43. $defined = wp_list_pluck( $this->get_defined_pluggable_functions(), 0 );
  44. $expected = $this->get_pluggable_function_signatures();
  45. foreach ( $expected as $function => $sig ) {
  46. $msg = 'Function: ' . $function . '()';
  47. $this->assertTrue( function_exists( $function ), $msg );
  48. $this->assertTrue( in_array( $function, $defined, true ), $msg );
  49. }
  50. }
  51. /**
  52. * Data provider for our pluggable function signature tests.
  53. *
  54. * @return array Data provider array of pluggable function names.
  55. */
  56. public function get_defined_pluggable_functions() {
  57. require_once ABSPATH . '/wp-admin/includes/upgrade.php';
  58. $test_functions = array(
  59. 'install_network',
  60. 'wp_install',
  61. 'wp_install_defaults',
  62. 'wp_new_blog_notification',
  63. 'wp_upgrade',
  64. 'install_global_terms',
  65. );
  66. $test_files = array(
  67. 'wp-includes/pluggable.php',
  68. );
  69. // Pluggable function signatures are not tested when an external object cache is in use. See #31491.
  70. if ( ! wp_using_ext_object_cache() ) {
  71. $test_files[] = 'wp-includes/cache.php';
  72. }
  73. $data = array();
  74. foreach ( $test_functions as $function ) {
  75. $data[] = array(
  76. $function,
  77. );
  78. }
  79. foreach ( $test_files as $file ) {
  80. preg_match_all( '#^\t?function (\w+)#m', file_get_contents( ABSPATH . '/' . $file ), $functions );
  81. foreach ( $functions[1] as $function ) {
  82. $data[] = array(
  83. $function,
  84. );
  85. }
  86. }
  87. return $data;
  88. }
  89. /**
  90. * Expected pluggable function signatures.
  91. *
  92. * @return array Array of signatures keyed by their function name.
  93. */
  94. public function get_pluggable_function_signatures() {
  95. $signatures = array(
  96. // wp-includes/pluggable.php:
  97. 'wp_set_current_user' => array(
  98. 'id',
  99. 'name' => '',
  100. ),
  101. 'wp_get_current_user' => array(),
  102. 'get_userdata' => array( 'user_id' ),
  103. 'get_user_by' => array( 'field', 'value' ),
  104. 'cache_users' => array( 'user_ids' ),
  105. 'wp_mail' => array(
  106. 'to',
  107. 'subject',
  108. 'message',
  109. 'headers' => '',
  110. 'attachments' => array(),
  111. ),
  112. 'wp_authenticate' => array( 'username', 'password' ),
  113. 'wp_logout' => array(),
  114. 'wp_validate_auth_cookie' => array(
  115. 'cookie' => '',
  116. 'scheme' => '',
  117. ),
  118. 'wp_generate_auth_cookie' => array(
  119. 'user_id',
  120. 'expiration',
  121. 'scheme' => 'auth',
  122. 'token' => '',
  123. ),
  124. 'wp_parse_auth_cookie' => array(
  125. 'cookie' => '',
  126. 'scheme' => '',
  127. ),
  128. 'wp_set_auth_cookie' => array(
  129. 'user_id',
  130. 'remember' => false,
  131. 'secure' => '',
  132. 'token' => '',
  133. ),
  134. 'wp_clear_auth_cookie' => array(),
  135. 'is_user_logged_in' => array(),
  136. 'auth_redirect' => array(),
  137. 'check_admin_referer' => array(
  138. 'action' => -1,
  139. 'query_arg' => '_wpnonce',
  140. ),
  141. 'check_ajax_referer' => array(
  142. 'action' => -1,
  143. 'query_arg' => false,
  144. 'die' => true,
  145. ),
  146. 'wp_redirect' => array(
  147. 'location',
  148. 'status' => 302,
  149. 'x_redirect_by' => 'WordPress',
  150. ),
  151. 'wp_sanitize_redirect' => array( 'location' ),
  152. '_wp_sanitize_utf8_in_redirect' => array( 'matches' ),
  153. 'wp_safe_redirect' => array(
  154. 'location',
  155. 'status' => 302,
  156. 'x_redirect_by' => 'WordPress',
  157. ),
  158. 'wp_validate_redirect' => array(
  159. 'location',
  160. 'default' => '',
  161. ),
  162. 'wp_notify_postauthor' => array(
  163. 'comment_id',
  164. 'deprecated' => null,
  165. ),
  166. 'wp_notify_moderator' => array( 'comment_id' ),
  167. 'wp_password_change_notification' => array( 'user' ),
  168. 'wp_new_user_notification' => array(
  169. 'user_id',
  170. 'deprecated' => null,
  171. 'notify' => '',
  172. ),
  173. 'wp_nonce_tick' => array(),
  174. 'wp_verify_nonce' => array(
  175. 'nonce',
  176. 'action' => -1,
  177. ),
  178. 'wp_create_nonce' => array( 'action' => -1 ),
  179. 'wp_salt' => array( 'scheme' => 'auth' ),
  180. 'wp_hash' => array(
  181. 'data',
  182. 'scheme' => 'auth',
  183. ),
  184. 'wp_hash_password' => array( 'password' ),
  185. 'wp_check_password' => array(
  186. 'password',
  187. 'hash',
  188. 'user_id' => '',
  189. ),
  190. 'wp_generate_password' => array(
  191. 'length' => 12,
  192. 'special_chars' => true,
  193. 'extra_special_chars' => false,
  194. ),
  195. 'wp_rand' => array(
  196. 'min' => 0,
  197. 'max' => 0,
  198. ),
  199. 'wp_set_password' => array( 'password', 'user_id' ),
  200. 'get_avatar' => array(
  201. 'id_or_email',
  202. 'size' => 96,
  203. 'default' => '',
  204. 'alt' => '',
  205. 'args' => null,
  206. ),
  207. 'wp_text_diff' => array(
  208. 'left_string',
  209. 'right_string',
  210. 'args' => null,
  211. ),
  212. // wp-admin/includes/schema.php:
  213. 'install_network' => array(),
  214. // wp-admin/includes/upgrade.php:
  215. 'wp_install' => array(
  216. 'blog_title',
  217. 'user_name',
  218. 'user_email',
  219. 'public',
  220. 'deprecated' => '',
  221. 'user_password' => '',
  222. 'language' => '',
  223. ),
  224. 'wp_install_defaults' => array( 'user_id' ),
  225. 'wp_new_blog_notification' => array( 'blog_title', 'blog_url', 'user_id', 'password' ),
  226. 'wp_upgrade' => array(),
  227. 'install_global_terms' => array(),
  228. );
  229. // Pluggable function signatures are not tested when an external object cache is in use. See #31491.
  230. if ( ! wp_using_ext_object_cache() ) {
  231. $signatures = array_merge(
  232. $signatures,
  233. array(
  234. // wp-includes/cache.php:
  235. 'wp_cache_add' => array(
  236. 'key',
  237. 'data',
  238. 'group' => '',
  239. 'expire' => 0,
  240. ),
  241. 'wp_cache_close' => array(),
  242. 'wp_cache_decr' => array(
  243. 'key',
  244. 'offset' => 1,
  245. 'group' => '',
  246. ),
  247. 'wp_cache_delete' => array(
  248. 'key',
  249. 'group' => '',
  250. ),
  251. 'wp_cache_flush' => array(),
  252. 'wp_cache_get' => array(
  253. 'key',
  254. 'group' => '',
  255. 'force' => false,
  256. 'found' => null,
  257. ),
  258. 'wp_cache_get_multiple' => array(
  259. 'keys',
  260. 'group' => '',
  261. 'force' => false,
  262. ),
  263. 'wp_cache_incr' => array(
  264. 'key',
  265. 'offset' => 1,
  266. 'group' => '',
  267. ),
  268. 'wp_cache_init' => array(),
  269. 'wp_cache_replace' => array(
  270. 'key',
  271. 'data',
  272. 'group' => '',
  273. 'expire' => 0,
  274. ),
  275. 'wp_cache_set' => array(
  276. 'key',
  277. 'data',
  278. 'group' => '',
  279. 'expire' => 0,
  280. ),
  281. 'wp_cache_switch_to_blog' => array( 'blog_id' ),
  282. 'wp_cache_add_global_groups' => array( 'groups' ),
  283. 'wp_cache_add_non_persistent_groups' => array( 'groups' ),
  284. 'wp_cache_reset' => array(),
  285. )
  286. );
  287. }
  288. return $signatures;
  289. }
  290. }