Hierarchy::get_classy_template()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 1
Metric Value
cc 3
eloc 5
nc 2
nop 0
dl 0
loc 9
rs 9.6666
c 4
b 1
f 1
1
<?php
2
/**
3
 * Implements WordPress template hierarchy.
4
 *
5
 * @package Classy
6
 */
7
8
namespace Classy;
9
10
/**
11
 * Class Hierarchy.
12
 */
13
class Hierarchy {
14
15
	/**
16
	 * Stores current request for multiple use.
17
	 *
18
	 * @var string/null
19
	 */
20
	protected static $current_request = null;
21
22
	/**
23
	 * Protected function to get current request type.
24
	 *
25
	 * @return string
26
	 */
27
	protected static function check_request() {
28
29
		if ( is_404() ) : return '404';
30
31
		elseif ( is_search() ) : return 'search';
32
33
		elseif ( is_front_page() ) : return 'front-page';
34
35
		elseif ( is_home() ) : return 'home';
36
37
		elseif ( is_post_type_archive() ) : return 'post_type_archive';
38
39
		elseif ( is_tax() ) : return 'taxonomy';
40
41
		elseif ( is_attachment() ) : return 'attachment';
42
43
		elseif ( is_single() ) : return 'single';
44
45
		elseif ( self::is_classy_template() ) : return 'classy-template';
46
47
		elseif ( is_page() ) : return 'page';
48
49
		elseif ( is_singular() ) : return 'singular';
50
51
		elseif ( is_category() ) : return 'category';
52
53
		elseif ( is_tag() ) : return 'tag';
54
55
		elseif ( is_author() ) : return 'author';
56
57
		elseif ( is_date() ) : return 'date';
58
59
		elseif ( is_archive() ) : return 'archive';
60
61
		elseif ( is_paged() ) : return 'paged';
62
63
		else :
64
65
			return 'index';
66
67
		endif;
68
	}
69
70
	/**
71
	 * Returns current request type.
72
	 *
73
	 * @return string
74
	 */
75
	public static function get_current_request() {
76
		if ( is_null( self::$current_request ) ) {
77
			self::$current_request = self::check_request();
78
		}
79
80
		return self::$current_request;
81
	}
82
83
84
	/**
85
	 * Returns file's absolute path.
86
	 *
87
	 * @param string $type View/scope.
88
	 * @param string $view Path to view ex: "post/archive".
89
	 *
90
	 * @return string Full file path.
91
	 */
92
	public static function get_file_path( $type = 'view', $view ) {
93
		$view = str_replace( '.', '/', $view );
94
95
		if ( 'view' === $type ) {
96
			return CLASSY_THEME_PATH . View::$folder . '/' . $view . '.blade.php';
97
		} elseif ( 'scope' === $type ) {
98
			return CLASSY_THEME_PATH . Scope::$folder . '/' . $view . '.php';
99
		}
100
101
		return '';
102
	}
103
104
	/**
105
	 * Checks if view exists.
106
	 *
107
	 * @param string $type View|scope.
108
	 * @param string $file In blade path format, ex: layout|header.
109
	 *
110
	 * @return boolean true|false
111
	 */
112
	public static function file_exists( $type = 'view', $file ) {
113
		return file_exists(
114
			self::get_file_path( $type, str_replace( '.', '/', $file ) )
115
		);
116
	}
117
118
	/**
119
	 * Returns view name for render, based on type of request.
120
	 *
121
	 * @param string $type View|scope.
122
	 * @param string $page Request type like: home, single etc.
123
	 *
124
	 * @return array|bool
125
	 */
126
	public static function get_available_file( $type = 'view', $page ) {
127
		$views = self::get_request_hierarchy_list( $page );
128
129
		foreach ( $views as $view ) {
130
			if ( self::file_exists( $type, $view ) ) {
0 ignored issues
show
Security Bug introduced by
It seems like $view defined by $view on line 129 can also be of type false; however, Classy\Hierarchy::file_exists() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
131
				return $view;
132
			}
133
		}
134
135
		return false;
136
	}
137
138
	/**
139
	 * Returns list of filenames to check, based on type of request.
140
	 *
141
	 * @param string $type Request type like: home, single etc.
142
	 *
143
	 * @return array
144
	 */
145
	private static function get_request_hierarchy_list( $type ) {
146
		$views = array();
147
148
		if ( 'home' === $type ) :
149
			$views[] = 'home';
150
		elseif ( 'single' === $type ) :
151
152
			$views[] = get_post_type() . '.single';
153
			$views[] = 'single';
154
155
		elseif ( 'post_type_archive' === $type ) :
156
157
			$views[] = get_post_type() . '.archive';
158
			$views[] = 'archive';
159
160
		elseif ( 'taxonomy' === $type ) :
161
162
			$term = get_queried_object();
163
164
			if ( ! empty( $term->slug ) ) {
165
				$taxonomy = $term->taxonomy;
166
167
				$views[] = "taxonomy.$taxonomy-{$term->slug}";
168
				$views[] = "taxonomy.$taxonomy";
169
			}
170
171
			$views[] = 'taxonomy.taxonomy';
172
			$views[] = 'taxonomy';
173
174
		elseif ( 'category' === $type ) :
175
176
			$category = get_queried_object();
177
178
			if ( ! empty( $category->slug ) ) {
179
				$views[] = "category.{$category->slug}";
180
				$views[] = "category.{$category->term_id}";
181
			}
182
183
			$views[] = 'category.category';
184
			$views[] = 'category';
185
186
		elseif ( 'attachment' === $type ) :
187
188
			$attachment = get_queried_object();
189
190
			if ( $attachment ) {
191
				if ( false !== strpos( $attachment->post_mime_type, '/' ) ) {
192
					list( $type, $subtype ) = explode( '/', $attachment->post_mime_type );
193
				} else {
194
					list( $type, $subtype ) = array( $attachment->post_mime_type, '' );
195
				}
196
197
				if ( ! empty( $subtype ) ) {
198
					$views[] = "attachment.{$type}.{$subtype}";
199
					$views[] = "attachment.{$subtype}";
200
201
					$views[] = "{$type}.{$subtype}";
202
					$views[] = "{$subtype}";
203
				}
204
205
				$views[] = "attachment.{$type}";
206
				$views[] = "{$type}";
207
			}
208
209
			$views[] = 'attachment.attachment';
210
			$views[] = 'attachment';
211
212
		elseif ( 'tag' === $type ) :
213
214
			$tag = get_queried_object();
215
216
			if ( ! empty( $tag->slug ) ) {
217
				$views[] = "post.tag.{$tag->slug}";
218
				$views[] = "post.tag.{$tag->term_id}";
219
220
				$views[] = "tag.{$tag->slug}";
221
				$views[] = "tag.{$tag->term_id}";
222
			}
223
224
			$views[] = 'post.tag';
225
			$views[] = 'tag';
226
227
		elseif ( 'author' === $type ) :
228
229
			$author = get_queried_object();
230
231
			if ( $author instanceof \WP_User ) {
0 ignored issues
show
Bug introduced by
The class WP_User does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
232
				$views[] = "post.author.{$author->user_nicename}";
233
				$views[] = "post.author.{$author->ID}";
234
235
				$views[] = "author.{$author->user_nicename}";
236
				$views[] = "author.{$author->ID}";
237
			}
238
239
			$views[] = 'post.author';
240
			$views[] = 'author';
241
242
		elseif ( 'front-page' === $type ) :
243
244
			$template = self::get_classy_template();
245
246
			if ( ! empty( $template ) ) {
247
				$views[] = $template;
248
				$views[] = 'page.' . $template;
249
				$views[] = 'template.' . $template;
250
			}
251
252
			$views[] = 'front-page.front-page';
253
			$views[] = 'front-page';
254
255
			$views[] = 'home.home';
256
			$views[] = 'home';
257
258
			$views = array_merge( $views, self::get_request_hierarchy_list( 'post_type_archive' ) );
259
260
		elseif ( 'classy-template' === $type ) :
261
262
			$template = self::get_classy_template();
263
264
			$views[] = $template;
265
			$views[] = 'page.' . $template;
266
			$views[] = 'template.' . $template;
267
			$views[] = 'page.page';
268
			$views[] = 'page';
269
270
		elseif ( 'page' === $type ) :
271
272
			$id = get_queried_object_id();
273
274
			$pagename = get_query_var( 'pagename' );
275
276
			if ( ! $pagename && $id ) {
277
				// If a static page is set as the front page, $pagename will not be set. Retrieve it from the queried object.
278
				if ( $post = get_queried_object() ) {
279
					$pagename = $post->post_name;
280
				}
281
			}
282
283
			if ( $pagename ) {
284
				$views[] = 'page.' . $pagename;
285
			}
286
287
			if ( $id ) {
288
				$views[] = 'page.' . $id;
289
			}
290
291
			$views[] = 'page.page';
292
			$views[] = 'page';
293
294
		else :
295
296
			$views[] = $type;
297
298
		endif;
299
300
		$views[] = 'index';
301
302
		return $views;
303
	}
304
305
	/**
306
	 * Checks if this is classy custom template
307
	 *
308
	 * @return boolean
309
	 */
310
	public static function is_classy_template() {
311
		return self::get_classy_template() ? true : false;
312
	}
313
314
	/**
315
	 * Returns classy template name or boolean if this is not classy template.
316
	 *
317
	 * @return mixed
318
	 */
319
	public static function get_classy_template() {
320
		preg_match( '/classy\-(.*)/', get_page_template_slug(), $matches );
321
322
		if ( ! empty( $matches ) && isset( $matches[1] ) ) {
323
			return $matches[1];
324
		}
325
326
		return false;
327
	}
328
}
329