Completed
Push — master ( af77e8...7d9d07 )
by Zack
11s
created

Gamajo_Template_Loader::__destruct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Template Loader for Plugins.
4
 *
5
 * @package   Gamajo_Template_Loader
6
 * @author    Gary Jones
7
 * @link      http://github.com/GaryJones/Gamajo-Template-Loader
8
 * @copyright 2013 Gary Jones
9
 * @license   GPL-2.0+
10
 * @version   1.2.0
11
 */
12
13
if ( ! class_exists( 'Gamajo_Template_Loader' ) ) {
14
15
	/**
16
	 * Template loader.
17
	 *
18
	 * Originally based on functions in Easy Digital Downloads (thanks Pippin!).
19
	 *
20
	 * When using in a plugin, create a new class that extends this one and just overrides the properties.
21
	 *
22
	 * @package Gamajo_Template_Loader
23
	 * @author  Gary Jones
24
	 */
25
	class Gamajo_Template_Loader {
26
		/**
27
		 * Prefix for filter names.
28
		 *
29
		 * @since 1.0.0
30
		 *
31
		 * @var string
32
		 */
33
		protected $filter_prefix = 'your_plugin';
34
35
		/**
36
		 * Directory name where custom templates for this plugin should be found in the theme.
37
		 *
38
		 * For example: 'your-plugin-templates'.
39
		 *
40
		 * @since 1.0.0
41
		 *
42
		 * @var string
43
		 */
44
		protected $theme_template_directory = 'plugin-templates';
45
46
		/**
47
		 * Reference to the root directory path of this plugin.
48
		 *
49
		 * Can either be a defined constant, or a relative reference from where the subclass lives.
50
		 *
51
		 * e.g. YOUR_PLUGIN_TEMPLATE or plugin_dir_path( dirname( __FILE__ ) ); etc.
52
		 *
53
		 * @since 1.0.0
54
		 *
55
		 * @var string
56
		 */
57
		protected $plugin_directory = 'YOUR_PLUGIN_DIR';
58
59
		/**
60
		 * Directory name where templates are found in this plugin.
61
		 *
62
		 * Can either be a defined constant, or a relative reference from where the subclass lives.
63
		 *
64
		 * e.g. 'templates' or 'includes/templates', etc.
65
		 *
66
		 * @since 1.1.0
67
		 *
68
		 * @var string
69
		 */
70
		protected $plugin_template_directory = 'templates';
71
72
		/**
73
		 * Clean up template data.
74
		 *
75
		 * @since 1.2.0
76
		 */
77
		public function __destruct() {
78
			$this->unset_template_data();
79
		}
80
81
		/**
82
		 * Retrieve a template part.
83
		 *
84
		 * @since 1.0.0
85
		 *
86
		 * @param string $slug Template slug.
87
		 * @param string $name Optional. Template variation name. Default null.
88
		 * @param bool   $load Optional. Whether to load template. Default true.
89
		 *
90
		 * @return string
91
		 */
92
		public function get_template_part( $slug, $name = null, $load = true ) {
93
			// Execute code for this part.
94
			do_action( 'get_template_part_' . $slug, $slug, $name );
95
96
			// Get files names of templates, for given slug and name.
97
			$templates = $this->get_template_file_names( $slug, $name );
98
99
			// Return the part that is found.
100
			return $this->locate_template( $templates, $load, false );
101
		}
102
103
		/**
104
		 * Make custom data available to template.
105
		 *
106
		 * Data is available to the template as properties under the `$data` variable.
107
		 * i.e. A value provided here under `$data['foo']` is available as `$data->foo`.
108
		 *
109
		 * When an input key has a hyphen, you can use `$data->{foo-bar}` in the template.
110
		 *
111
		 * @since 1.2.0
112
		 *
113
		 * @param array  $data     Custom data for the template.
114
		 * @param string $var_name Optional. Variable under which the custom data is available in the template.
115
		 *                         Default is 'data'.
116
		 */
117
		public function set_template_data( array $data, $var_name = 'data' ) {
118
			global $wp_query;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
119
120
			$wp_query->query_vars[ $var_name ] = (object) $data;
121
		}
122
123
		/**
124
		 * Remove access to custom data in template.
125
		 *
126
		 * Good to use once the final template part has been requested.
127
		 *
128
		 * @since 1.2.0
129
		 */
130
		public function unset_template_data() {
131
			global $wp_query;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
132
133
			if ( isset( $wp_query->query_vars['data'] ) ) {
134
				unset( $wp_query->query_vars['data'] );
135
			}
136
		}
137
138
		/**
139
		 * Given a slug and optional name, create the file names of templates.
140
		 *
141
		 * @since 1.0.0
142
		 *
143
		 * @param string $slug Template slug.
144
		 * @param string $name Template variation name.
145
		 *
146
		 * @return array
147
		 */
148
		protected function get_template_file_names( $slug, $name ) {
149
			$templates = array();
150
			if ( isset( $name ) ) {
151
				$templates[] = $slug . '-' . $name . '.php';
152
			}
153
			$templates[] = $slug . '.php';
154
155
			/**
156
			 * Allow template choices to be filtered.
157
			 *
158
			 * The resulting array should be in the order of most specific first, to least specific last.
159
			 * e.g. 0 => recipe-instructions.php, 1 => recipe.php
160
			 *
161
			 * @since 1.0.0
162
			 *
163
			 * @param array  $templates Names of template files that should be looked for, for given slug and name.
164
			 * @param string $slug      Template slug.
165
			 * @param string $name      Template variation name.
166
			 */
167
			return apply_filters( $this->filter_prefix . '_get_template_part', $templates, $slug, $name );
168
		}
169
170
		/**
171
		 * Retrieve the name of the highest priority template file that exists.
172
		 *
173
		 * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which
174
		 * inherit from a parent theme can just overload one file. If the template is
175
		 * not found in either of those, it looks in the theme-compat folder last.
176
		 *
177
		 * @since 1.0.0
178
		 *
179
		 * @param string|array $template_names Template file(s) to search for, in order.
180
		 * @param bool         $load           If true the template file will be loaded if it is found.
181
		 * @param bool         $require_once   Whether to require_once or require. Default true.
182
		 *                                     Has no effect if $load is false.
183
		 *
184
		 * @return string The template filename if one is located.
185
		 */
186
		public function locate_template( $template_names, $load = false, $require_once = true ) {
187
			// No file found yet.
188
			$located = false;
189
190
			// Remove empty entries.
191
			$template_names = array_filter( (array) $template_names );
192
			$template_paths = $this->get_template_paths();
193
194
			// Try to find a template file.
195
			foreach ( $template_names as $template_name ) {
196
				// Trim off any slashes from the template name.
197
				$template_name = ltrim( $template_name, '/' );
198
199
				// Try locating this template file by looping through the template paths.
200
				foreach ( $template_paths as $template_path ) {
201
					if ( file_exists( $template_path . $template_name ) ) {
202
						$located = $template_path . $template_name;
203
						break 2;
204
					}
205
				}
206
			}
207
208
			if ( $load && $located ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $located of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
209
				load_template( $located, $require_once );
210
			}
211
212
			return $located;
213
		}
214
215
		/**
216
		 * Return a list of paths to check for template locations.
217
		 *
218
		 * Default is to check in a child theme (if relevant) before a parent theme, so that themes which inherit from a
219
		 * parent theme can just overload one file. If the template is not found in either of those, it looks in the
220
		 * theme-compat folder last.
221
		 *
222
		 * @since 1.0.0
223
		 *
224
		 * @return mixed|void
225
		 */
226
		protected function get_template_paths() {
227
			$theme_directory = trailingslashit( $this->theme_template_directory );
228
229
			$file_paths = array(
230
				10  => trailingslashit( get_template_directory() ) . $theme_directory,
231
				100 => $this->get_templates_dir(),
232
			);
233
234
			// Only add this conditionally, so non-child themes don't redundantly check active theme twice.
235
			if ( is_child_theme() ) {
236
				$file_paths[1] = trailingslashit( get_stylesheet_directory() ) . $theme_directory;
237
			}
238
239
			/**
240
			 * Allow ordered list of template paths to be amended.
241
			 *
242
			 * @since 1.0.0
243
			 *
244
			 * @param array $var Default is directory in child theme at index 1, parent theme at 10, and plugin at 100.
245
			 */
246
			$file_paths = apply_filters( $this->filter_prefix . '_template_paths', $file_paths );
247
248
			// Sort the file paths based on priority.
249
			ksort( $file_paths, SORT_NUMERIC );
250
251
			return array_map( 'trailingslashit', $file_paths );
252
		}
253
254
		/**
255
		 * Return the path to the templates directory in this plugin.
256
		 *
257
		 * May be overridden in subclass.
258
		 *
259
		 * @since 1.0.0
260
		 *
261
		 * @return string
262
		 */
263
		protected function get_templates_dir() {
264
			return trailingslashit( $this->plugin_directory ) . $this->plugin_template_directory;
265
		}
266
	}
267
}
268