forked from GaryJones/Gamajo-Template-Loader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
class-gamajo-template-loader.php
313 lines (276 loc) · 9.14 KB
/
class-gamajo-template-loader.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
<?php
/**
* Template Loader for Plugins.
*
* @package Gamajo_Template_Loader
* @author Gary Jones
* @link http://github.com/GaryJones/Gamajo-Template-Loader
* @copyright 2013 Gary Jones
* @license GPL-2.0-or-later
* @version 1.3.1
*/
if ( ! class_exists( 'Gamajo_Template_Loader' ) ) {
/**
* Template loader.
*
* Originally based on functions in Easy Digital Downloads (thanks Pippin!).
*
* When using in a plugin, create a new class that extends this one and just overrides the properties.
*
* @package Gamajo_Template_Loader
* @author Gary Jones
*/
class Gamajo_Template_Loader {
/**
* Prefix for filter names.
*
* @since 1.0.0
*
* @var string
*/
protected $filter_prefix = 'your_plugin';
/**
* Directory name where custom templates for this plugin should be found in the theme.
*
* For example: 'your-plugin-templates'.
*
* @since 1.0.0
*
* @var string
*/
protected $theme_template_directory = 'plugin-templates';
/**
* Reference to the root directory path of this plugin.
*
* Can either be a defined constant, or a relative reference from where the subclass lives.
*
* e.g. YOUR_PLUGIN_TEMPLATE or plugin_dir_path( dirname( __FILE__ ) ); etc.
*
* @since 1.0.0
*
* @var string
*/
protected $plugin_directory = 'YOUR_PLUGIN_DIR';
/**
* Directory name where templates are found in this plugin.
*
* Can either be a defined constant, or a relative reference from where the subclass lives.
*
* e.g. 'templates' or 'includes/templates', etc.
*
* @since 1.1.0
*
* @var string
*/
protected $plugin_template_directory = 'templates';
/**
* Internal use only: Store located template paths.
*
* @var array
*/
private $template_path_cache = array();
/**
* Internal use only: Store variable names used for template data.
*
* Means unset_template_data() can remove all custom references from $wp_query.
*
* Initialized to contain the default 'data'.
*
* @var array
*/
private $template_data_var_names = array( 'data' );
/**
* Clean up template data.
*
* @since 1.2.0
*/
public function __destruct() {
$this->unset_template_data();
}
/**
* Retrieve a template part.
*
* @since 1.0.0
*
* @param string $slug Template slug.
* @param string $name Optional. Template variation name. Default null.
* @param bool $load Optional. Whether to load template. Default true.
* @return string
*/
public function get_template_part( $slug, $name = null, $load = true ) {
// Execute code for this part.
do_action( 'get_template_part_' . $slug, $slug, $name );
do_action( $this->filter_prefix . '_get_template_part_' . $slug, $slug, $name );
// Get files names of templates, for given slug and name.
$templates = $this->get_template_file_names( $slug, $name );
// Return the part that is found.
return $this->locate_template( $templates, $load, false );
}
/**
* Make custom data available to template.
*
* Data is available to the template as properties under the `$data` variable.
* i.e. A value provided here under `$data['foo']` is available as `$data->foo`.
*
* When an input key has a hyphen, you can use `$data->{foo-bar}` in the template.
*
* @since 1.2.0
*
* @param mixed $data Custom data for the template.
* @param string $var_name Optional. Variable under which the custom data is available in the template.
* Default is 'data'.
* @return Gamajo_Template_Loader
*/
public function set_template_data( $data, $var_name = 'data' ) {
global $wp_query;
$wp_query->query_vars[ $var_name ] = (object) $data;
// Add $var_name to custom variable store if not default value.
if ( 'data' !== $var_name ) {
$this->template_data_var_names[] = $var_name;
}
return $this;
}
/**
* Remove access to custom data in template.
*
* Good to use once the final template part has been requested.
*
* @since 1.2.0
*
* @return Gamajo_Template_Loader
*/
public function unset_template_data() {
global $wp_query;
// Remove any duplicates from the custom variable store.
$custom_var_names = array_unique( $this->template_data_var_names );
// Remove each custom data reference from $wp_query.
foreach ( $custom_var_names as $var ) {
if ( isset( $wp_query->query_vars[ $var ] ) ) {
unset( $wp_query->query_vars[ $var ] );
}
}
return $this;
}
/**
* Given a slug and optional name, create the file names of templates.
*
* @since 1.0.0
*
* @param string $slug Template slug.
* @param string $name Template variation name.
* @return array
*/
protected function get_template_file_names( $slug, $name ) {
$templates = array();
if ( isset( $name ) ) {
$templates[] = $slug . '-' . $name . '.php';
}
$templates[] = $slug . '.php';
/**
* Allow template choices to be filtered.
*
* The resulting array should be in the order of most specific first, to least specific last.
* e.g. 0 => recipe-instructions.php, 1 => recipe.php
*
* @since 1.0.0
*
* @param array $templates Names of template files that should be looked for, for given slug and name.
* @param string $slug Template slug.
* @param string $name Template variation name.
*/
return apply_filters( $this->filter_prefix . '_get_template_part', $templates, $slug, $name );
}
/**
* Retrieve the name of the highest priority template file that exists.
*
* Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which
* inherit from a parent theme can just overload one file. If the template is
* not found in either of those, it looks in the theme-compat folder last.
*
* @since 1.0.0
*
* @param string|array $template_names Template file(s) to search for, in order.
* @param bool $load If true the template file will be loaded if it is found.
* @param bool $require_once Whether to require_once or require. Default true.
* Has no effect if $load is false.
* @return string The template filename if one is located.
*/
public function locate_template( $template_names, $load = false, $require_once = true ) {
// Use $template_names as a cache key - either first element of array or the variable itself if it's a string.
$cache_key = is_array( $template_names ) ? $template_names[0] : $template_names;
// If the key is in the cache array, we've already located this file.
if ( isset( $this->template_path_cache[ $cache_key ] ) ) {
$located = $this->template_path_cache[ $cache_key ];
} else {
// No file found yet.
$located = false;
// Remove empty entries.
$template_names = array_filter( (array) $template_names );
$template_paths = $this->get_template_paths();
// Try to find a template file.
foreach ( $template_names as $template_name ) {
// Trim off any slashes from the template name.
$template_name = ltrim( $template_name, '/' );
// Try locating this template file by looping through the template paths.
foreach ( $template_paths as $template_path ) {
if ( file_exists( $template_path . $template_name ) ) {
$located = $template_path . $template_name;
// Store the template path in the cache.
$this->template_path_cache[ $cache_key ] = $located;
break 2;
}
}
}
}
if ( $load && $located ) {
load_template( $located, $require_once );
}
return $located;
}
/**
* Return a list of paths to check for template locations.
*
* Default is to check in a child theme (if relevant) before a parent theme, so that themes which inherit from a
* parent theme can just overload one file. If the template is not found in either of those, it looks in the
* theme-compat folder last.
*
* @since 1.0.0
*
* @return mixed|void
*/
protected function get_template_paths() {
$theme_directory = trailingslashit( $this->theme_template_directory );
$file_paths = array(
10 => trailingslashit( get_template_directory() ) . $theme_directory,
100 => $this->get_templates_dir(),
);
// Only add this conditionally, so non-child themes don't redundantly check active theme twice.
if ( get_stylesheet_directory() !== get_template_directory() ) {
$file_paths[1] = trailingslashit( get_stylesheet_directory() ) . $theme_directory;
}
/**
* Allow ordered list of template paths to be amended.
*
* @since 1.0.0
*
* @param array $var Default is directory in child theme at index 1, parent theme at 10, and plugin at 100.
*/
$file_paths = apply_filters( $this->filter_prefix . '_template_paths', $file_paths );
// Sort the file paths based on priority.
ksort( $file_paths, SORT_NUMERIC );
return array_map( 'trailingslashit', $file_paths );
}
/**
* Return the path to the templates directory in this plugin.
*
* May be overridden in subclass.
*
* @since 1.0.0
*
* @return string
*/
protected function get_templates_dir() {
return trailingslashit( $this->plugin_directory ) . $this->plugin_template_directory;
}
}
}