Completed
Pull Request — master (#848)
by Jared
02:48
created

Timber::init_constants()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 2
eloc 2
nc 2
nop 0
1
<?php
2
3
/**
4
 * Timber Class.
5
 *
6
 * Main class called Timber for this plugin.
7
 *
8
 * Usage:
9
 *  $posts = Timber::get_posts();
10
 *  $posts = Timber::get_posts('post_type = article')
11
 *  $posts = Timber::get_posts(array('post_type' => 'article', 'category_name' => 'sports')); // uses wp_query format.
12
 *  $posts = Timber::get_posts(array(23,24,35,67), 'InkwellArticle');
13
 *
14
 *  $context = Timber::get_context(); // returns wp favorites!
15
 *  $context['posts'] = $posts;
16
 *  Timber::render('index.twig', $context);
17
 */
18
class Timber {
19
20
	public static $locations;
21
	public static $dirname;
22
	public static $twig_cache = false;
23
	public static $cache = false;
24
	public static $auto_meta = true;
25
	public static $autoescape = false;
26
27
	/**
28
	 * @codeCoverageIgnore
29
	 */
30
	public function __construct() {
31
		if ( !defined('ABSPATH') ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
32
			return;
33
		}
34
		$this->test_compatibility();
35
		$this->init_constants();
36
		$this->init();
37
	}
38
39
	/**
40
	 * Tests whether we can use Timber
41
	 * @codeCoverageIgnore
42
	 * @return
43
	 */
44
	protected function test_compatibility() {
45
		if ( is_admin() || $_SERVER['PHP_SELF'] == '/wp-login.php' ) {
0 ignored issues
show
introduced by
Detected usage of a non-validated input variable: $_SERVER
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
46
			return;
47
		}
48
		if ( version_compare( phpversion(), '5.3.0', '<' ) && !is_admin() ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
49
			trigger_error( 'Timber requires PHP 5.3.0 or greater. You have '.phpversion(), E_USER_ERROR );
50
		}
51
		if ( !class_exists( 'Twig_Autoloader' ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
52
			trigger_error( 'You have not run "composer install" to download required dependencies for Timber, you can read more on https://github.com/jarednova/timber#installation', E_USER_ERROR );
53
		}
54
	}
55
56
	function init_constants() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
57
		defined( "TIMBER_LOC" ) or define( "TIMBER_LOC", realpath( dirname(__DIR__) ) );
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal TIMBER_LOC does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
58
	}
59
60
	/**
61
	 * @codeCoverageIgnore
62
	 */
63
	protected function init() {
64
		TimberTwig::init();
65
		TimberRoutes::init( $this );
0 ignored issues
show
Deprecated Code introduced by
The method TimberRoutes::init() has been deprecated with message: since 0.21.1 use Upstatement/routes instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
66
		TimberImageHelper::init();
67
		TimberAdmin::init();
68
		TimberIntegrations::init();
69
	}
70
71
	/* Post Retrieval Routine
72
	================================ */
73
74
	/**
75
	 * Get post.
76
	 *
77
	 * @param mixed   $query
78
	 * @param string  $PostClass
79
	 * @return array|bool|null
80
	 */
81
	public static function get_post( $query = false, $PostClass = 'TimberPost' ) {
82
		return TimberPostGetter::get_post( $query, $PostClass );
83
	}
84
85
	/**
86
	 * Get posts.
87
	 *
88
	 * @param mixed   $query
89
	 * @param string  $PostClass
90
	 * @return array|bool|null
91
	 */
92
	public static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
93
		return TimberPostGetter::get_posts( $query, $PostClass, $return_collection );
94
	}
95
96
	/**
97
	 * Query post.
98
	 *
99
	 * @param mixed   $query
100
	 * @param string  $PostClass
101
	 * @return array|bool|null
102
	 */
103
	public static function query_post( $query = false, $PostClass = 'TimberPost' ) {
104
		return TimberPostGetter::query_post( $query, $PostClass );
105
	}
106
107
	/**
108
	 * Query posts.
109
	 *
110
	 * @param mixed   $query
111
	 * @param string  $PostClass
112
	 * @return array|bool|null
0 ignored issues
show
Documentation introduced by
Should the return type not be TimberPostsCollection|TimberQueryIterator?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
113
	 */
114
	public static function query_posts( $query = false, $PostClass = 'TimberPost' ) {
115
		return TimberPostGetter::query_posts( $query, $PostClass );
116
	}
117
118
	/**
119
	 * WP_Query has posts.
120
	 *
121
	 * @return bool
122
	 * @deprecated since 0.20.0
123
	 */
124
	static function wp_query_has_posts() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
125
		return TimberPostGetter::wp_query_has_posts();
126
	}
127
128
	/* Term Retrieval
129
	================================ */
130
131
	/**
132
	 * Get terms.
133
	 *
134
	 * @param string|array $args
0 ignored issues
show
Documentation introduced by
Should the type for parameter $args not be string|array|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
135
	 * @param array   $maybe_args
136
	 * @param string  $TermClass
137
	 * @return mixed
138
	 */
139
	public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'TimberTerm' ) {
140
		return TimberTermGetter::get_terms( $args, $maybe_args, $TermClass );
141
	}
142
143
	/* Site Retrieval
144
	================================ */
145
146
	/**
147
	 * Get sites.
148
	 *
149
	 * @param array|bool $blog_ids
150
	 * @return array
151
	 */
152
	public static function get_sites( $blog_ids = false ) {
153
		if ( !is_array( $blog_ids ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
154
			global $wpdb;
155
			$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id ASC" );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
156
		}
157
		$return = array();
158
		foreach ( $blog_ids as $blog_id ) {
159
			$return[] = new TimberSite( $blog_id );
160
		}
161
		return $return;
162
	}
163
164
165
	/*  Template Setup and Display
166
	================================ */
167
168
	/**
169
	 * Get context.
170
	 *
171
	 * @return array
172
	 */
173
	public static function get_context() {
174
		$data = array();
175
		$data['http_host'] = 'http://' . TimberURLHelper::get_host();
176
		$data['wp_title'] = TimberHelper::get_wp_title();
177
		$data['wp_head'] = TimberHelper::function_wrapper( 'wp_head' );
178
		$data['wp_footer'] = TimberHelper::function_wrapper( 'wp_footer' );
179
		$data['body_class'] = implode( ' ', get_body_class() );
180
181
		$data['site'] = new TimberSite();
182
		$data['theme'] = $data['site']->theme;
183
184
		$data['posts'] = Timber::query_posts();
185
186
		$data = apply_filters( 'timber_context', $data );
187
		$data = apply_filters( 'timber/context', $data );
188
		return $data;
189
	}
190
191
	/**
192
	 * Compile function.
193
	 *
194
	 * @param array   $filenames
195
	 * @param array   $data
196
	 * @param bool    $expires
197
	 * @param string  $cache_mode
198
	 * @param bool    $via_render
199
	 * @return bool|string
200
	 */
201
	public static function compile( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT, $via_render = false ) {
202
		$caller = self::get_calling_script_dir();
203
		$caller_file = self::get_calling_script_file();
0 ignored issues
show
Deprecated Code introduced by
The method Timber::get_calling_script_file() has been deprecated with message: since 0.20.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
204
		$caller_file = apply_filters( 'timber_calling_php_file', $caller_file );
0 ignored issues
show
Unused Code introduced by
$caller_file is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
205
		$loader = new TimberLoader( $caller );
206
		$file = $loader->choose_template( $filenames );
207
		$output = '';
208
		if ( is_null( $data ) ) {
209
			$data = array();
210
		}
211
		if ( strlen( $file ) ) {
212
			if ( $via_render ) {
213
				$file = apply_filters( 'timber_render_file', $file );
214
				$data = apply_filters( 'timber_render_data', $data );
215
			} else {
216
				$file = apply_filters( 'timber_compile_file', $file );
217
				$data = apply_filters( 'timber_compile_data', $data );
218
			}
219
			$output = $loader->render( $file, $data, $expires, $cache_mode );
220
		}
221
		do_action( 'timber_compile_done' );
222
		return $output;
223
	}
224
225
	/**
226
	 * Compile string.
227
	 *
228
	 * @param string  $string a string with twig variables.
229
	 * @param array   $data   an array with data in it.
230
	 * @return  bool|string
231
	 */
232
	public static function compile_string( $string, $data = array() ) {
233
		$dummy_loader = new TimberLoader();
234
		$dummy_loader->get_twig();
235
		$loader = new Twig_Loader_String();
0 ignored issues
show
Deprecated Code introduced by
The class Twig_Loader_String has been deprecated with message: since 1.18.1 (to be removed in 2.0)

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
236
		$twig = new Twig_Environment( $loader );
237
		$twig = apply_filters( 'timber/twig/filters', $twig );
238
		$twig = apply_filters( 'twig_apply_filters', $twig );
239
		return $twig->render( $string, $data );
240
	}
241
242
	/**
243
	 * Fetch function.
244
	 *
245
	 * @param array   $filenames
246
	 * @param array   $data
247
	 * @param bool    $expires
248
	 * @param string  $cache_mode
249
	 * @return bool|string
250
	 */
251
	public static function fetch( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT ) {
252
		if ( $expires === true ) {
0 ignored issues
show
introduced by
Found "=== true". Use Yoda Condition checks, you must
Loading history...
253
			//if this is reading as true; the user probably is using the old $echo param
254
			//so we should move all vars up by a spot
255
			$expires = $cache_mode;
256
			$cache_mode = TimberLoader::CACHE_USE_DEFAULT;
257
		}
258
		$output = self::compile( $filenames, $data, $expires, $cache_mode, true );
0 ignored issues
show
Bug introduced by
It seems like $expires defined by $cache_mode on line 255 can also be of type string; however, Timber::compile() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
259
		$output = apply_filters( 'timber_compile_result', $output );
260
		return $output;
261
	}
262
263
	/**
264
	 * Render function.
265
	 *
266
	 * @param array   $filenames
267
	 * @param array   $data
268
	 * @param bool    $expires
269
	 * @param string  $cache_mode
270
	 * @return bool|string
271
	 */
272
	public static function render( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT ) {
273
		$output = static::fetch( $filenames, $data, $expires, $cache_mode );
274
		echo $output;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$output'
Loading history...
275
		return $output;
276
	}
277
278
	/**
279
	 * Render string.
280
	 *
281
	 * @param string  $string a string with twig variables.
282
	 * @param array   $data   an array with data in it.
283
	 * @return  bool|string
284
	 */
285
	public static function render_string( $string, $data = array() ) {
286
		$compiled = self::compile_string( $string, $data );
287
		echo $compiled;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$compiled'
Loading history...
288
		return $compiled;
289
	}
290
291
292
	/*  Sidebar
293
	================================ */
294
295
	/**
296
	 * Get sidebar.
297
	 *
298
	 * @param string  $sidebar
299
	 * @param array   $data
300
	 * @return bool|string
301
	 */
302
	public static function get_sidebar( $sidebar = '', $data = array() ) {
303
		if ( $sidebar == '' ) {
304
			$sidebar = 'sidebar.php';
305
		}
306
		if ( strstr( strtolower( $sidebar ), '.php' ) ) {
307
			return self::get_sidebar_from_php( $sidebar, $data );
308
		}
309
		return self::compile( $sidebar, $data );
0 ignored issues
show
Documentation introduced by
$sidebar is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
310
	}
311
312
	/**
313
	 * Get sidebar from PHP
314
	 *
315
	 * @param string  $sidebar
316
	 * @param array   $data
317
	 * @return string
318
	 */
319
	public static function get_sidebar_from_php( $sidebar = '', $data ) {
320
		$caller = self::get_calling_script_dir();
321
		$loader = new TimberLoader();
322
		$uris = $loader->get_locations( $caller );
323
		ob_start();
324
		$found = false;
325
		foreach ( $uris as $uri ) {
326
			if ( file_exists( trailingslashit( $uri ) . $sidebar ) ) {
327
				include trailingslashit( $uri ) . $sidebar;
328
				$found = true;
329
				break;
330
			}
331
		}
332
		if ( !$found ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
333
			TimberHelper::error_log( 'error loading your sidebar, check to make sure the file exists' );
334
		}
335
		$ret = ob_get_contents();
336
		ob_end_clean();
337
		return $ret;
338
	}
339
340
	/* Widgets
341
	================================ */
342
343
	/**
344
	 * Get widgets.
345
	 *
346
	 * @param int     $widget_id
347
	 * @return TimberFunctionWrapper
348
	 */
349
	public static function get_widgets( $widget_id ) {
350
		return TimberHelper::function_wrapper( 'dynamic_sidebar', array( $widget_id ), true );
351
	}
352
353
354
	/*  Routes
355
	================================ */
356
357
	/**
358
	 * Add route.
359
	 *
360
	 * @param string  $route
361
	 * @param callable $callback
362
	 * @param array   $args
363
	 * @deprecated since 0.20.0
364
	 */
365
	public static function add_route( $route, $callback, $args = array() ) {
366
		Routes::map( $route, $callback, $args );
367
	}
368
369
	/**
370
	 * Load template.
371
	 *
372
	 * @deprecated since 0.20.0
373
	 */
374
	public static function load_template( $template, $query = false, $status_code = 200, $tparams = false ) {
375
		return Routes::load( $template, $tparams, $query, $status_code );
0 ignored issues
show
Documentation introduced by
$query is of type boolean, but the function expects a false|object<WP_Query>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
376
	}
377
378
	/**
379
	 * Load view.
380
	 *
381
	 * @deprecated since 0.20.2
382
	 */
383
	public static function load_view( $template, $query = false, $status_code = 200, $tparams = false ) {
384
		return Routes::load( $template, $tparams, $query, $status_code );
0 ignored issues
show
Documentation introduced by
$query is of type boolean, but the function expects a false|object<WP_Query>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
385
	}
386
387
388
	/*  Pagination
389
	================================ */
390
391
	/**
392
	 * Get pagination.
393
	 *
394
	 * @param array   $prefs
395
	 * @return array mixed
396
	 */
397
	public static function get_pagination( $prefs = array() ) {
398
		global $wp_query;
399
		global $paged;
400
		global $wp_rewrite;
401
		$args = array();
402
		$args['total'] = ceil( $wp_query->found_posts / $wp_query->query_vars['posts_per_page'] );
403
		if ( $wp_rewrite->using_permalinks() ) {
404
			$url = explode( '?', get_pagenum_link( 0 ) );
405
			if ( isset( $url[1] ) ) {
406
				parse_str( $url[1], $query );
407
				$args['add_args'] = $query;
408
			}
409
			$args['format'] = 'page/%#%';
410
			$args['base'] = trailingslashit( $url[0] ).'%_%';
411
		} else {
412
			$big = 999999999;
413
			$args['base'] = str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) );
414
		}
415
		$args['type'] = 'array';
416
		$args['current'] = max( 1, get_query_var( 'paged' ) );
417
		$args['mid_size'] = max( 9 - $args['current'], 3 );
418
		if ( is_int( $prefs ) ) {
419
			$args['mid_size'] = $prefs - 2;
420
		} else {
421
			$args = array_merge( $args, $prefs );
422
		}
423
		$data = array();
424
		$data['current'] = $args['current'];
425
		$data['total'] = $args['total'];
426
		$data['pages'] = TimberHelper::paginate_links( $args );
0 ignored issues
show
Documentation introduced by
$args is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
427
		$next = get_next_posts_page_link( $args['total'] );
428
		if ( $next ) {
429
			$data['next'] = array( 'link' => untrailingslashit( $next ), 'class' => 'page-numbers next' );
430
		}
431
		$prev = previous_posts( false );
432
		if ( $prev ) {
433
			$data['prev'] = array( 'link' => untrailingslashit( $prev ), 'class' => 'page-numbers prev' );
434
		}
435
		if ( $paged < 2 ) {
436
			$data['prev'] = '';
437
		}
438
		return $data;
439
	}
440
441
	/*  Utility
442
	================================ */
443
444
	/**
445
	 * Get calling script dir.
446
	 *
447
	 * @return string
448
	 */
449
	public static function get_calling_script_dir( $offset = 0 ) {
450
		$caller = self::get_calling_script_file( $offset );
0 ignored issues
show
Deprecated Code introduced by
The method Timber::get_calling_script_file() has been deprecated with message: since 0.20.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
451
		if ( !is_null( $caller ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
452
			$pathinfo = pathinfo( $caller );
453
			$dir = $pathinfo['dirname'];
454
			return $dir;
455
		}
456
	}
457
458
	/**
459
	 * Get calling script file.
460
	 *
461
	 * @param int     $offset
462
	 * @return string|null
463
	 * @deprecated since 0.20.0
464
	 */
465
	public static function get_calling_script_file( $offset = 0 ) {
466
		$caller = null;
467
		$backtrace = debug_backtrace();
468
		$i = 0;
469
		foreach ( $backtrace as $trace ) {
470
			if ( array_key_exists('file', $trace) && $trace['file'] != __FILE__ ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
471
				$caller = $trace['file'];
472
				break;
473
			}
474
			$i++;
475
		}
476
		if ( $offset ) {
477
			$caller = $backtrace[$i + $offset]['file'];
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
478
		}
479
		return $caller;
480
	}
481
482
483
}
484