Complex classes like PodsView often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PodsView, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
6 | class PodsView { |
||
|
|||
7 | |||
8 | /** |
||
9 | * @var array $cache_modes Array of available cache modes |
||
10 | */ |
||
11 | public static $cache_modes = array( 'none', 'transient', 'site-transient', 'cache', 'option-cache' ); |
||
12 | |||
13 | /** |
||
14 | * @return \PodsView |
||
15 | */ |
||
16 | private function __construct() { |
||
17 | |||
18 | // !nope |
||
19 | } |
||
20 | |||
21 | /** |
||
22 | * @static |
||
23 | * |
||
24 | * @param string $view Path of the view file |
||
25 | * @param array|null $data (optional) Data to pass on to the template |
||
26 | * @param bool|int|array $expires (optional) Time in seconds for the cache to expire, if 0 no expiration. |
||
27 | * @param string $cache_mode (optional) Decides the caching method to use for the view. |
||
28 | * |
||
29 | * @return bool|mixed|null|string|void |
||
30 | * |
||
31 | * @since 2.0 |
||
32 | */ |
||
33 | public static function view( $view, $data = null, $expires = false, $cache_mode = 'cache' ) { |
||
34 | |||
35 | /** |
||
36 | * Override the value of $view. For example, using Pods AJAX View. |
||
37 | * |
||
38 | * To use, set first param to true. If that param in not null, this method returns its value. |
||
39 | * |
||
40 | * @param null|bool If not set to null, this filter overrides the rest of the method. |
||
41 | * @param string $view Path of the view file |
||
42 | * @param array|null $data (optional) Data to pass on to the template |
||
43 | * @param bool|int|array $expires (optional) Time in seconds for the cache to expire, if 0 no expiration. |
||
44 | * @param string $cache_mode (optional) Decides the caching method to use for the view. |
||
45 | * |
||
46 | * @since 2.4.1 |
||
47 | */ |
||
48 | $filter_check = apply_filters( 'pods_view_alt_view', null, $view, $data, $expires, $cache_mode ); |
||
49 | |||
50 | if ( null !== $filter_check ) { |
||
51 | return $filter_check; |
||
52 | } |
||
53 | |||
54 | // Advanced $expires handling |
||
55 | $expires = self::expires( $expires, $cache_mode ); |
||
56 | |||
57 | if ( ! in_array( $cache_mode, self::$cache_modes ) ) { |
||
58 | $cache_mode = 'cache'; |
||
59 | } |
||
60 | |||
61 | // Support my-view.php?custom-key=X#hash keying for cache |
||
62 | $view_id = ''; |
||
63 | |||
64 | if ( ! is_array( $view ) ) { |
||
65 | $view_q = explode( '?', $view ); |
||
66 | |||
67 | if ( 1 < count( $view_q ) ) { |
||
68 | $view_id = '?' . $view_q[1]; |
||
69 | |||
70 | $view = $view_q[0]; |
||
71 | } |
||
72 | |||
73 | $view_h = explode( '#', $view ); |
||
74 | |||
75 | if ( 1 < count( $view_h ) ) { |
||
76 | $view_id .= '#' . $view_h[1]; |
||
77 | |||
78 | $view = $view_h[0]; |
||
79 | } |
||
80 | |||
81 | // Support dynamic tags! |
||
82 | $view_id = pods_evaluate_tags( $view_id ); |
||
83 | } |
||
84 | |||
85 | $view = apply_filters( 'pods_view_inc', $view, $data, $expires, $cache_mode ); |
||
86 | |||
87 | $view_key = $view; |
||
88 | |||
89 | if ( is_array( $view_key ) ) { |
||
90 | $view_key = implode( '-', $view_key ) . '.php'; |
||
91 | } |
||
92 | |||
93 | if ( false !== realpath( $view_key ) ) { |
||
94 | $view_key = realpath( $view_key ); |
||
95 | } |
||
96 | |||
97 | $pods_ui_dir = realpath( PODS_DIR . 'ui/' ); |
||
98 | $pods_components_dir = realpath( PODS_DIR . 'components/' ); |
||
99 | $abspath_dir = realpath( ABSPATH ); |
||
100 | |||
101 | $cache_key = pods_str_replace( $abspath_dir, '/', $view_key, 1 ); |
||
102 | |||
103 | $output = false; |
||
104 | |||
105 | $caching = false; |
||
106 | |||
107 | if ( false !== $expires && false === strpos( $view_key, $pods_ui_dir ) && false === strpos( $view_key, $pods_components_dir ) ) { |
||
108 | $caching = true; |
||
109 | } |
||
110 | |||
111 | if ( $caching ) { |
||
112 | $output = self::get( 'pods-view-' . $cache_key . $view_id, $cache_mode, 'pods_view' ); |
||
113 | } |
||
114 | |||
115 | if ( false === $output || null === $output ) { |
||
116 | $output = self::get_template_part( $view, $data ); |
||
117 | } |
||
118 | |||
119 | if ( false !== $output && $caching ) { |
||
120 | self::set( 'pods-view-' . $cache_key . $view_id, $output, $expires, $cache_mode, 'pods_view' ); |
||
121 | } |
||
122 | |||
123 | $output = apply_filters( 'pods_view_output_' . $cache_key, $output, $view, $data, $expires, $cache_mode ); |
||
124 | $output = apply_filters( 'pods_view_output', $output, $view, $data, $expires, $cache_mode ); |
||
125 | |||
126 | return $output; |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * Get the cache key, salted with current Pods version, peppered with md5 if too long |
||
131 | * |
||
132 | * @param string $key |
||
133 | * @param string $group_key |
||
134 | * |
||
135 | * @return string |
||
136 | * |
||
137 | * @since 2.6.2 |
||
138 | */ |
||
139 | public static function get_key( $key, $group_key = '' ) { |
||
140 | |||
141 | // Add some salt |
||
142 | $key .= '-' . PODS_VERSION; |
||
143 | |||
144 | // Patch for limitations in DB |
||
145 | if ( 44 < strlen( $group_key . $key ) ) { |
||
146 | $key = md5( $key ); |
||
147 | } |
||
148 | |||
149 | return $key; |
||
150 | |||
151 | } |
||
152 | |||
153 | /** |
||
154 | * @static |
||
155 | * |
||
156 | * @param string $key Key for the cache |
||
157 | * @param string $cache_mode (optional) Decides the caching method to use for the view. |
||
158 | * @param string $group (optional) Set the group of the value. |
||
159 | * @param string $callback (optional) Callback function to run to set the value if not cached. |
||
160 | * |
||
161 | * @return bool|mixed|null|void |
||
162 | * |
||
163 | * @since 2.0 |
||
164 | */ |
||
165 | public static function get( $key, $cache_mode = 'cache', $group = '', $callback = null ) { |
||
166 | |||
167 | $object_cache = false; |
||
168 | |||
169 | if ( isset( $GLOBALS['wp_object_cache'] ) && is_object( $GLOBALS['wp_object_cache'] ) ) { |
||
170 | $object_cache = true; |
||
171 | } |
||
172 | |||
173 | if ( ! in_array( $cache_mode, self::$cache_modes ) ) { |
||
174 | $cache_mode = 'cache'; |
||
175 | } |
||
176 | |||
177 | $group_key = 'pods_'; |
||
178 | |||
179 | if ( ! empty( $group ) ) { |
||
180 | $group_key = $group . '_'; |
||
181 | } |
||
182 | |||
183 | $original_key = $key; |
||
184 | |||
185 | // Get proper cache key |
||
186 | $key = self::get_key( $key, $group_key ); |
||
187 | |||
188 | $value = null; |
||
189 | |||
190 | $called = false; |
||
191 | |||
192 | $pods_nocache = pods_var_raw( 'pods_nocache' ); |
||
193 | $nocache = array(); |
||
194 | |||
195 | if ( pods_is_admin() && null !== $pods_nocache ) { |
||
196 | if ( 1 < strlen( $pods_nocache ) ) { |
||
197 | $nocache = explode( ',', $pods_nocache ); |
||
198 | } else { |
||
199 | $nocache = self::$cache_modes; |
||
200 | } |
||
201 | } |
||
202 | |||
203 | if ( apply_filters( 'pods_view_cache_alt_get', false, $cache_mode, $group_key . $key, $original_key, $group ) ) { |
||
204 | $value = apply_filters( 'pods_view_cache_alt_get_value', $value, $cache_mode, $group_key . $key, $original_key, $group ); |
||
205 | } elseif ( 'transient' === $cache_mode && ! in_array( $cache_mode, $nocache ) ) { |
||
206 | $value = get_transient( $group_key . $key ); |
||
207 | } elseif ( 'site-transient' === $cache_mode && ! in_array( $cache_mode, $nocache ) ) { |
||
208 | $value = get_site_transient( $group_key . $key ); |
||
209 | } elseif ( 'cache' === $cache_mode && $object_cache && ! in_array( $cache_mode, $nocache ) ) { |
||
210 | $value = wp_cache_get( $key, ( empty( $group ) ? 'pods_view' : $group ) ); |
||
211 | } elseif ( 'option-cache' === $cache_mode && ! in_array( $cache_mode, $nocache ) ) { |
||
212 | global $_wp_using_ext_object_cache; |
||
213 | |||
214 | $pre = apply_filters( 'pre_transient_' . $key, false ); |
||
215 | |||
216 | if ( false !== $pre ) { |
||
217 | $value = $pre; |
||
218 | } elseif ( $_wp_using_ext_object_cache ) { |
||
219 | $value = wp_cache_get( $key, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
220 | $timeout = wp_cache_get( '_timeout_' . $key, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
221 | |||
222 | if ( ! empty( $timeout ) && $timeout < time() ) { |
||
223 | if ( is_callable( $callback ) ) { |
||
224 | // Callback function should do it's own set/update for cache |
||
225 | $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode ); |
||
226 | |||
227 | if ( null !== $callback_value && false !== $callback_value ) { |
||
228 | $value = $callback_value; |
||
229 | } |
||
230 | |||
231 | $called = true; |
||
232 | } else { |
||
233 | $value = false; |
||
234 | |||
235 | wp_cache_delete( $key, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
236 | wp_cache_delete( '_timeout_' . $key, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
237 | } |
||
238 | } |
||
239 | } else { |
||
240 | $transient_option = '_pods_option_' . $key; |
||
241 | $transient_timeout = '_pods_option_timeout_' . $key; |
||
242 | |||
243 | $value = get_option( $transient_option ); |
||
244 | $timeout = get_option( $transient_timeout ); |
||
245 | |||
246 | if ( ! empty( $timeout ) && $timeout < time() ) { |
||
247 | if ( is_callable( $callback ) ) { |
||
248 | // Callback function should do it's own set/update for cache |
||
249 | $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode ); |
||
250 | |||
251 | if ( null !== $callback_value && false !== $callback_value ) { |
||
252 | $value = $callback_value; |
||
253 | } |
||
254 | |||
255 | $called = true; |
||
256 | } else { |
||
257 | $value = false; |
||
258 | |||
259 | delete_option( $transient_option ); |
||
260 | delete_option( $transient_timeout ); |
||
261 | } |
||
262 | } |
||
263 | }//end if |
||
264 | |||
265 | if ( false !== $value ) { |
||
266 | $value = apply_filters( 'transient_' . $key, $value ); |
||
267 | } |
||
268 | } else { |
||
269 | $value = false; |
||
270 | }//end if |
||
271 | |||
272 | if ( false === $value && is_callable( $callback ) && ! $called ) { |
||
273 | // Callback function should do it's own set/update for cache |
||
274 | $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode ); |
||
275 | |||
276 | if ( null !== $callback_value && false !== $callback_value ) { |
||
277 | $value = $callback_value; |
||
278 | } |
||
279 | } |
||
280 | |||
281 | $value = apply_filters( 'pods_view_get_' . $cache_mode, $value, $original_key, $group ); |
||
282 | |||
283 | return $value; |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * @static |
||
288 | * |
||
289 | * Set a cached value |
||
290 | * |
||
291 | * @param string $key Key for the cache |
||
292 | * @param mixed $value Value to add to the cache |
||
293 | * @param int $expires (optional) Time in seconds for the cache to expire, if 0 no expiration. |
||
294 | * @param string $cache_mode (optional) Decides the caching method to use for the view. |
||
295 | * @param string $group (optional) Set the group of the value. |
||
296 | * |
||
297 | * @return bool|mixed|null|string|void |
||
298 | * |
||
299 | * @since 2.0 |
||
300 | */ |
||
301 | public static function set( $key, $value, $expires = 0, $cache_mode = null, $group = '' ) { |
||
302 | |||
303 | $object_cache = false; |
||
304 | |||
305 | if ( isset( $GLOBALS['wp_object_cache'] ) && is_object( $GLOBALS['wp_object_cache'] ) ) { |
||
306 | $object_cache = true; |
||
307 | } |
||
308 | |||
309 | // Advanced $expires handling |
||
310 | $expires = self::expires( $expires, $cache_mode ); |
||
311 | |||
312 | if ( ! in_array( $cache_mode, self::$cache_modes ) ) { |
||
313 | $cache_mode = 'cache'; |
||
314 | } |
||
315 | |||
316 | $group_key = 'pods_'; |
||
317 | |||
318 | if ( ! empty( $group ) ) { |
||
319 | $group_key = $group . '_'; |
||
320 | } |
||
321 | |||
322 | $original_key = $key; |
||
323 | |||
324 | // Get proper cache key |
||
325 | $key = self::get_key( $key, $group_key ); |
||
326 | |||
327 | if ( apply_filters( 'pods_view_cache_alt_set', false, $cache_mode, $group_key . $key, $original_key, $value, $expires, $group ) ) { |
||
328 | return $value; |
||
329 | } elseif ( 'transient' === $cache_mode ) { |
||
330 | set_transient( $group_key . $key, $value, $expires ); |
||
331 | } elseif ( 'site-transient' === $cache_mode ) { |
||
332 | set_site_transient( $group_key . $key, $value, $expires ); |
||
333 | } elseif ( 'cache' === $cache_mode && $object_cache ) { |
||
334 | wp_cache_set( $key, $value, ( empty( $group ) ? 'pods_view' : $group ), $expires ); |
||
335 | } elseif ( 'option-cache' === $cache_mode ) { |
||
336 | global $_wp_using_ext_object_cache; |
||
337 | |||
338 | $value = apply_filters( 'pre_set_transient_' . $key, $value ); |
||
339 | |||
340 | if ( $_wp_using_ext_object_cache ) { |
||
341 | $result = wp_cache_set( $key, $value, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
342 | |||
343 | if ( $expires ) { |
||
344 | $result = wp_cache_set( '_timeout_' . $key, $expires, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
345 | } |
||
346 | } else { |
||
347 | $transient_timeout = '_pods_option_timeout_' . $key; |
||
348 | $key = '_pods_option_' . $key; |
||
349 | |||
350 | if ( false === get_option( $key ) ) { |
||
351 | if ( $expires ) { |
||
352 | add_option( $transient_timeout, time() + $expires, '', 'no' ); |
||
353 | } |
||
354 | |||
355 | $result = add_option( $key, $value, '', 'no' ); |
||
356 | } else { |
||
357 | if ( $expires ) { |
||
358 | update_option( $transient_timeout, time() + $expires ); |
||
359 | } |
||
360 | |||
361 | $result = update_option( $key, $value ); |
||
362 | } |
||
363 | }//end if |
||
364 | |||
365 | if ( $result ) { |
||
366 | do_action( 'set_transient_' . $key ); |
||
367 | do_action( 'setted_transient', $key ); |
||
368 | } |
||
369 | }//end if |
||
370 | |||
371 | do_action( 'pods_view_set_' . $cache_mode, $original_key, $value, $expires, $group ); |
||
372 | |||
373 | return $value; |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * @static |
||
378 | * |
||
379 | * Clear a cached value |
||
380 | * |
||
381 | * @param string|bool $key Key for the cache |
||
382 | * @param string $cache_mode (optional) Decides the caching method to use for the view. |
||
383 | * @param string $group (optional) Set the group. |
||
384 | * |
||
385 | * @return bool |
||
386 | * |
||
387 | * @since 2.0 |
||
388 | */ |
||
389 | public static function clear( $key = true, $cache_mode = null, $group = '' ) { |
||
390 | |||
391 | $object_cache = false; |
||
392 | |||
393 | if ( isset( $GLOBALS['wp_object_cache'] ) && is_object( $GLOBALS['wp_object_cache'] ) ) { |
||
394 | $object_cache = true; |
||
395 | } |
||
396 | |||
397 | global $wpdb; |
||
398 | |||
399 | if ( ! in_array( $cache_mode, self::$cache_modes ) ) { |
||
400 | $cache_mode = 'cache'; |
||
401 | } |
||
402 | |||
403 | $group_key = 'pods_'; |
||
404 | |||
405 | if ( ! empty( $group ) ) { |
||
406 | $group_key = $group . '_'; |
||
407 | } |
||
408 | |||
409 | $full_key = $original_key = $key; |
||
410 | |||
411 | if ( true !== $key ) { |
||
412 | // Get proper cache key |
||
413 | $key = self::get_key( $key, $group_key ); |
||
414 | |||
415 | $full_key = $group_key . $key; |
||
416 | } |
||
417 | |||
418 | if ( apply_filters( 'pods_view_cache_alt_set', false, $cache_mode, $full_key, $original_key, '', 0, $group ) ) { |
||
419 | return true; |
||
420 | } elseif ( 'transient' === $cache_mode ) { |
||
421 | if ( true === $key ) { |
||
422 | $group_key = pods_sanitize_like( $group_key ); |
||
423 | |||
424 | $wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE option_name LIKE '_transient_{$group_key}%'" ); |
||
425 | |||
426 | if ( $object_cache ) { |
||
427 | wp_cache_flush(); |
||
428 | } |
||
429 | } else { |
||
430 | delete_transient( $group_key . $key ); |
||
431 | } |
||
432 | } elseif ( 'site-transient' === $cache_mode ) { |
||
433 | if ( true === $key ) { |
||
434 | $group_key = pods_sanitize_like( $group_key ); |
||
435 | |||
436 | $wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE option_name LIKE '_site_transient_{$group_key}%'" ); |
||
437 | |||
438 | if ( $object_cache ) { |
||
439 | wp_cache_flush(); |
||
440 | } |
||
441 | } else { |
||
442 | delete_site_transient( $group_key . $key ); |
||
443 | } |
||
444 | } elseif ( 'cache' === $cache_mode && $object_cache ) { |
||
445 | if ( true === $key ) { |
||
446 | wp_cache_flush(); |
||
447 | } else { |
||
448 | wp_cache_delete( ( empty( $key ) ? 'pods_view' : $key ), ( empty( $group ) ? 'pods_view' : $group ) ); |
||
449 | } |
||
450 | } elseif ( 'option-cache' === $cache_mode ) { |
||
451 | global $_wp_using_ext_object_cache; |
||
452 | |||
453 | do_action( 'delete_transient_' . $key, $key ); |
||
454 | |||
455 | if ( $_wp_using_ext_object_cache ) { |
||
456 | $result = wp_cache_delete( $key, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
457 | |||
458 | wp_cache_delete( '_timeout_' . $key, ( empty( $group ) ? 'pods_option_cache' : $group ) ); |
||
459 | } else { |
||
460 | $option_timeout = '_pods_option_timeout_' . $key; |
||
461 | $option = '_pods_option_' . $key; |
||
462 | |||
463 | $result = delete_option( $option ); |
||
464 | |||
465 | if ( $result ) { |
||
466 | delete_option( $option_timeout ); |
||
467 | } |
||
468 | } |
||
469 | |||
470 | if ( $result ) { |
||
471 | do_action( 'deleted_transient', $key ); |
||
472 | } |
||
473 | }//end if |
||
474 | |||
475 | do_action( 'pods_view_clear_' . $cache_mode, $original_key, $group ); |
||
476 | |||
477 | return true; |
||
478 | } |
||
479 | |||
480 | /** |
||
481 | * @static |
||
482 | * |
||
483 | * @param $_view |
||
484 | * @param null|array $_data |
||
485 | * |
||
486 | * @return bool|mixed|string|void |
||
487 | */ |
||
488 | public static function get_template_part( $_view, $_data = null ) { |
||
489 | |||
490 | /* |
||
491 | to be reviewed later, should have more checks and restrictions like a whitelist etc |
||
492 | if ( 0 === strpos( $_view, 'http://' ) || 0 === strpos( $_view, 'https://' ) ) { |
||
493 | $_view = apply_filters( 'pods_view_url_include', $_view ); |
||
494 | |||
495 | if ( empty( $_view ) || ( defined( 'PODS_REMOTE_VIEWS' ) && PODS_REMOTE_VIEWS ) ) |
||
496 | return ''; |
||
497 | |||
498 | $response = wp_remote_get( $_view ); |
||
499 | |||
500 | return wp_remote_retrieve_body( $response ); |
||
501 | } |
||
502 | */ |
||
503 | |||
504 | $_view = self::locate_template( $_view ); |
||
505 | |||
506 | if ( empty( $_view ) ) { |
||
507 | return $_view; |
||
508 | } |
||
509 | |||
510 | if ( ! empty( $_data ) && is_array( $_data ) ) { |
||
511 | extract( $_data, EXTR_SKIP ); |
||
512 | } |
||
513 | |||
514 | ob_start(); |
||
515 | require $_view; |
||
516 | $output = ob_get_clean(); |
||
517 | |||
518 | return $output; |
||
519 | } |
||
520 | |||
521 | /** |
||
522 | * @static |
||
523 | * |
||
524 | * @param $_view |
||
525 | * |
||
526 | * @return bool|mixed|string|void |
||
527 | */ |
||
528 | private static function locate_template( $_view ) { |
||
600 | |||
601 | /** |
||
602 | * Advanced $expires handling |
||
603 | * |
||
604 | * @param array|bool|int $expires |
||
605 | * @param string $cache_mode |
||
606 | * |
||
607 | * @return bool|int |
||
608 | * |
||
609 | * @since 2.7 |
||
610 | * @static |
||
611 | */ |
||
612 | public static function expires( $expires, $cache_mode = 'cache' ) { |
||
667 | |||
668 | } |
||
669 |