PluginProbe
Custom 404 Pro / trunk
Custom 404 Pro vtrunk
3.15.2 3.15.4 3.15.5 3.15.6 3.16.0 3.15.1 3.15.0 3.14.1 3.14.0 3.13.0 trunk 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.1.5 1.1.6 1.2.0 1.3.10 1.3.12 1.3.5 All 100 releases
custom-404-pro / tests / bootstrap.php

bootstrap.php in Custom 404 Pro trunk, at tests/bootstrap.php

311 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Test bootstrap: stubs $wpdb so class constructors can reference it without WordPress loaded.
4 *
5 * @package Custom_404_Pro
6 */
7
8 global $wpdb;
9 $wpdb = new stdClass(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- intentional stub for unit tests
10 $wpdb->prefix = 'wp_';
11
12 // Simple filter/action registries used by stubs below.
13 $GLOBALS['_test_filters'] = array();
14 $GLOBALS['_test_actions'] = array();
15 $GLOBALS['_load_plugin_textdomain_calls'] = array();
16 $GLOBALS['_test_options'] = array();
17 $GLOBALS['_test_transients'] = array();
18 $GLOBALS['_test_is_404'] = false;
19 $GLOBALS['_test_permalinks'] = array();
20 $GLOBALS['_test_redirect_url'] = null;
21 $GLOBALS['_test_redirect_status'] = null;
22
23 // WordPress time constants.
24 if ( ! defined( 'MINUTE_IN_SECONDS' ) ) {
25 define( 'MINUTE_IN_SECONDS', 60 );
26 }
27 if ( ! defined( 'HOUR_IN_SECONDS' ) ) {
28 define( 'HOUR_IN_SECONDS', 3600 );
29 }
30 if ( ! defined( 'DAY_IN_SECONDS' ) ) {
31 define( 'DAY_IN_SECONDS', 86400 );
32 }
33
34 // Mirror the plugin version constant, read from the plugin file rather than
35 // hardcoded, so version-dependent behaviour (asset cache busting, the db-version
36 // upgrade gate) is testable without loading WordPress.
37 if ( ! defined( 'CUSTOM_404_PRO_VERSION' ) ) {
38 $_c404p_main = file_get_contents( dirname( __DIR__ ) . '/custom-404-pro.php' );
39 preg_match( "/define\(\s*'CUSTOM_404_PRO_VERSION',\s*'([^']+)'\s*\)/", $_c404p_main, $_c404p_match );
40 define( 'CUSTOM_404_PRO_VERSION', $_c404p_match[1] ?? '0.0.0' );
41 unset( $_c404p_main, $_c404p_match );
42 }
43
44 /**
45 * Stub for WordPress apply_filters().
46 *
47 * Runs any callbacks registered via add_filter() for $tag.
48 *
49 * @param string $tag The filter hook name.
50 * @param mixed $value The value to filter.
51 * @param mixed ...$args Additional arguments passed to callbacks.
52 * @return mixed The filtered value.
53 */
54 function apply_filters( string $tag, $value, ...$args ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.matchFound
55 if ( isset( $GLOBALS['_test_filters'][ $tag ] ) ) {
56 foreach ( $GLOBALS['_test_filters'][ $tag ] as $callback ) {
57 $value = $callback( $value, ...$args );
58 }
59 }
60 return $value;
61 }
62
63 /**
64 * Stub for WordPress add_filter().
65 *
66 * @param string $tag The filter hook name.
67 * @param callable $callback The callback to register.
68 */
69 function add_filter( string $tag, callable $callback ) {
70 $GLOBALS['_test_filters'][ $tag ][] = $callback;
71 }
72
73 /**
74 * Stub for WordPress has_filter().
75 *
76 * Returns true when at least one callback is registered for $tag via add_filter().
77 *
78 * @param string $tag The filter hook name.
79 * @return bool
80 */
81 function has_filter( string $tag ): bool {
82 return ! empty( $GLOBALS['_test_filters'][ $tag ] );
83 }
84
85 /**
86 * Stub for Polylang pll_get_post().
87 *
88 * Returns the value of $GLOBALS['_pll_get_post_return']; defaults to false.
89 *
90 * @param int $post_id The post ID to translate.
91 * @param string $lang The target language slug.
92 * @return int|false
93 */
94 function pll_get_post( int $post_id, string $lang ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
95 return $GLOBALS['_pll_get_post_return'] ?? false;
96 }
97
98 /**
99 * Stub for Polylang pll_current_language().
100 *
101 * Returns the value of $GLOBALS['_pll_current_language']; defaults to 'en'.
102 *
103 * @return string
104 */
105 function pll_current_language(): string {
106 return $GLOBALS['_pll_current_language'] ?? 'en';
107 }
108
109 /**
110 * Stub for Polylang pll_default_language().
111 *
112 * Returns the value of $GLOBALS['_pll_default_language']; defaults to 'en'.
113 *
114 * @return string
115 */
116 function pll_default_language(): string {
117 return $GLOBALS['_pll_default_language'] ?? 'en';
118 }
119
120 /**
121 * Stub for WordPress add_action().
122 *
123 * @param string $tag The action hook name.
124 * @param callable $callback The callback to register.
125 * @param mixed ...$args Additional arguments (priority, accepted_args) — ignored by stub.
126 */
127 function add_action( string $tag, $callback, ...$args ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
128 $GLOBALS['_test_actions'][ $tag ][] = array( $callback );
129 }
130
131 /**
132 * Stub for WordPress plugin_dir_path().
133 *
134 * @param string $file Absolute path to the reference file.
135 * @return string Trailing-slashed directory path.
136 */
137 function plugin_dir_path( string $file ): string {
138 return rtrim( dirname( $file ), DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR;
139 }
140
141 /**
142 * Stub for WordPress plugin_basename().
143 *
144 * Returns a path relative to the plugin root (two levels up from $file).
145 *
146 * @param string $file Absolute path.
147 * @return string Relative plugin basename.
148 */
149 function plugin_basename( string $file ): string {
150 $plugins_dir = dirname( dirname( $file ) );
151 return ltrim( str_replace( $plugins_dir, '', $file ), DIRECTORY_SEPARATOR );
152 }
153
154 /**
155 * Stub for WordPress load_plugin_textdomain().
156 *
157 * Records the call so tests can assert on the arguments passed.
158 *
159 * @param string $domain Text domain.
160 * @param string|false $deprecated Deprecated — always false.
161 * @param string|false $plugin_rel_path Relative path to the languages directory.
162 */
163 function load_plugin_textdomain( string $domain, $deprecated = false, $plugin_rel_path = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
164 $GLOBALS['_load_plugin_textdomain_calls'][] = array(
165 'domain' => $domain,
166 'plugin_rel_path' => $plugin_rel_path,
167 );
168 }
169
170 /**
171 * Stub for WordPress get_option().
172 *
173 * Returns the value stored in the test options registry, or $default if not set.
174 *
175 * @param string $option Option name.
176 * @param mixed $default Default value.
177 * @return mixed
178 */
179 function get_option( string $option, $default = false ) {
180 return array_key_exists( $option, $GLOBALS['_test_options'] )
181 ? $GLOBALS['_test_options'][ $option ]
182 : $default;
183 }
184
185 /**
186 * Stub for WordPress update_option().
187 *
188 * Stores a value in the test options registry.
189 *
190 * @param string $option Option name.
191 * @param mixed $value Value to store.
192 * @return bool Always true.
193 */
194 function update_option( string $option, $value ) {
195 $GLOBALS['_test_options'][ $option ] = $value;
196 return true;
197 }
198
199 /**
200 * Stub for WordPress add_option().
201 *
202 * Stores a value only when the option is not already set (mirrors WordPress behaviour).
203 *
204 * @param string $option Option name.
205 * @param mixed $value Value to store.
206 * @return bool True if the option was added, false if it already existed.
207 */
208 function add_option( string $option, $value ) {
209 if ( array_key_exists( $option, $GLOBALS['_test_options'] ) ) {
210 return false;
211 }
212 $GLOBALS['_test_options'][ $option ] = $value;
213 return true;
214 }
215
216 /**
217 * Stub for WordPress delete_option().
218 *
219 * Removes a value from the test options registry.
220 *
221 * @param string $option Option name.
222 * @return bool Always true.
223 */
224 function delete_option( string $option ): bool {
225 unset( $GLOBALS['_test_options'][ $option ] );
226 return true;
227 }
228
229 /**
230 * Stub for WordPress get_transient().
231 *
232 * Returns the value stored in the test transient registry, or false if not set.
233 *
234 * @param string $transient Transient name.
235 * @return mixed Stored value, or false if not set.
236 */
237 function get_transient( string $transient ) {
238 return $GLOBALS['_test_transients'][ $transient ] ?? false;
239 }
240
241 /**
242 * Stub for WordPress set_transient().
243 *
244 * Stores a value in the test transient registry.
245 *
246 * @param string $transient Transient name.
247 * @param mixed $value Value to store.
248 * @param int $expiration Ignored in unit tests.
249 * @return bool Always true.
250 */
251 function set_transient( string $transient, $value, int $expiration = 0 ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
252 $GLOBALS['_test_transients'][ $transient ] = $value;
253 return true;
254 }
255
256 /**
257 * Stub for WordPress delete_transient().
258 *
259 * Removes a value from the test transient registry.
260 *
261 * @param string $transient Transient name.
262 * @return bool Always true.
263 */
264 function delete_transient( string $transient ): bool {
265 unset( $GLOBALS['_test_transients'][ $transient ] );
266 return true;
267 }
268
269 /**
270 * Stub for WordPress is_404().
271 *
272 * Returns the value of $GLOBALS['_test_is_404']; defaults to false.
273 *
274 * @return bool
275 */
276 function is_404(): bool {
277 return $GLOBALS['_test_is_404'] ?? false;
278 }
279
280 /**
281 * Stub for WordPress get_permalink().
282 *
283 * Returns the value from $GLOBALS['_test_permalinks'][$post_id], or false if not set.
284 *
285 * @param int $post_id Post ID.
286 * @return string|false
287 */
288 function get_permalink( $post_id = 0 ) {
289 return $GLOBALS['_test_permalinks'][ $post_id ] ?? false;
290 }
291
292 /**
293 * Stub for WordPress wp_safe_redirect().
294 *
295 * Captures the redirect URL and status in globals and returns false so that
296 * the gated exit( ) in custom_404_pro_redirect() does not terminate the process.
297 *
298 * @param string $location Redirect URL.
299 * @param int $status HTTP status code.
300 * @return bool Always false.
301 */
302 function wp_safe_redirect( string $location, int $status = 302 ): bool {
303 $GLOBALS['_test_redirect_url'] = $location;
304 $GLOBALS['_test_redirect_status'] = $status;
305 return false;
306 }
307
308 require_once dirname( __DIR__ ) . '/admin/class-helpers.php';
309 require_once dirname( __DIR__ ) . '/admin/class-adminclass.php';
310 require_once dirname( __DIR__ ) . '/includes/class-pluginclass.php';
311