Completed
Push — master ( 21157a...9cf7be )
by Zack
84:58 queued 65:12
created

Gamajo_Template_Loader   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0
Metric Value
wmc 12
lcom 1
cbo 0
dl 0
loc 198
rs 10
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.1.0
11
 */
12
13
/**
14
 * Template loader.
15
 *
16
 * Originally based on functions in Easy Digital Downloads (thanks Pippin!).
17
 *
18
 * When using in a plugin, create a new class that extends this one and just overrides the properties.
19
 *
20
 * @package Gamajo_Template_Loader
21
 * @author  Gary Jones
22
 */
23
class Gamajo_Template_Loader {
24
	/**
25
	 * Prefix for filter names.
26
	 *
27
	 * @since 1.0.0
28
	 *
29
	 * @type string
30
	 */
31
	protected $filter_prefix = 'your_plugin';
32
33
	/**
34
	 * Directory name where custom templates for this plugin should be found in the theme.
35
	 *
36
	 * @since 1.0.0
37
	 *
38
	 * @type string
39
	 */
40
	protected $theme_template_directory = 'your-plugin'; // or 'your-plugin-templates' etc.
41
42
	/**
43
	 * Reference to the root directory path of this plugin.
44
	 *
45
	 * Can either be a defined constant, or a relative reference from where the subclass lives.
46
	 *
47
	 * @since 1.0.0
48
	 *
49
	 * @type string
50
	 */
51
	protected $plugin_directory = YOUR_PLUGIN_DIR; // or plugin_dir_path( dirname( __FILE__ ) ); etc.
52
53
	/**
54
	 * Directory name where templates are found in this plugin.
55
	 *
56
	 * Can either be a defined constant, or a relative reference from where the subclass lives.
57
	 *
58
	 * @since 1.1.0
59
	 *
60
	 * @type string
61
	 */
62
	protected $plugin_template_directory = 'templates'; // or includes/templates, etc.
63
64
	/**
65
	 * Retrieve a template part.
66
	 *
67
	 * @since 1.0.0
68
	 *
69
	 * @uses Gamajo_Template_Loader::get_template_possble_parts() Create file names of templates.
70
	 * @uses Gamajo_Template_Loader::locate_template() Retrieve the name of the highest priority template
71
	 *     file that exists.
72
	 *
73
	 * @param string  $slug
74
	 * @param string  $name Optional. Default null.
75
	 * @param bool    $load Optional. Default true.
76
	 *
77
	 * @return string
78
	 */
79
	public function get_template_part( $slug, $name = null, $load = true ) {
80
		// Execute code for this part
81
		do_action( 'get_template_part_' . $slug, $slug, $name );
82
83
		// Get files names of templates, for given slug and name.
84
		$templates = $this->get_template_file_names( $slug, $name );
85
86
		// Return the part that is found
87
		return $this->locate_template( $templates, $load, false );
88
	}
89
90
	/**
91
	 * Given a slug and optional name, create the file names of templates.
92
	 *
93
	 * @since 1.0.0
94
	 *
95
	 * @param string  $slug
96
	 * @param string  $name
97
	 *
98
	 * @return array
99
	 */
100
	protected function get_template_file_names( $slug, $name ) {
101
		$templates = array();
102
		if ( isset( $name ) ) {
103
			$templates[] = $slug . '-' . $name . '.php';
104
		}
105
		$templates[] = $slug . '.php';
106
107
		/**
108
		 * Allow template choices to be filtered.
109
		 *
110
		 * The resulting array should be in the order of most specific first, to least specific last.
111
		 * e.g. 0 => recipe-instructions.php, 1 => recipe.php
112
		 *
113
		 * @since 1.0.0
114
		 *
115
		 * @param array $templates Names of template files that should be looked for, for given slug and name.
116
		 * @param string $slug Template slug.
117
		 * @param string $name Template name.
118
		 */
119
		return apply_filters( $this->filter_prefix . '_get_template_part', $templates, $slug, $name );
120
	}
121
122
	/**
123
	 * Retrieve the name of the highest priority template file that exists.
124
	 *
125
	 * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which
126
	 * inherit from a parent theme can just overload one file. If the template is
127
	 * not found in either of those, it looks in the theme-compat folder last.
128
	 *
129
	 * @since 1.0.0
130
	 *
131
	 * @uses Gamajo_Tech_Loader::get_template_paths() Return a list of paths to check for template locations.
132
	 *
133
	 * @param string|array $template_names Template file(s) to search for, in order.
134
	 * @param bool         $load           If true the template file will be loaded if it is found.
135
	 * @param bool         $require_once   Whether to require_once or require. Default true.
136
	 *   Has no effect if $load is false.
137
	 *
138
	 * @return string The template filename if one is located.
139
	 */
140
	public function locate_template( $template_names, $load = false, $require_once = true ) {
141
		// No file found yet
142
		$located = false;
143
144
		// Remove empty entries
145
		$template_names = array_filter( (array) $template_names );
146
		$template_paths = $this->get_template_paths();
147
148
		// Try to find a template file
149
		foreach ( $template_names as $template_name ) {
150
			// Trim off any slashes from the template name
151
			$template_name = ltrim( $template_name, '/' );
152
153
			// Try locating this template file by looping through the template paths
154
			foreach ( $template_paths as $template_path ) {
155
				if ( file_exists( $template_path . $template_name ) ) {
156
					$located = $template_path . $template_name;
157
					break 2;
158
				}
159
			}
160
		}
161
162
		if ( $load && $located ) {
163
			load_template( $located, $require_once );
164
		}
165
166
		return $located;
167
	}
168
169
	/**
170
	 * Return a list of paths to check for template locations.
171
	 *
172
	 * Default is to check in a child theme (if relevant) before a parent theme, so that themes which inherit from a
173
	 * parent theme can just overload one file. If the template is not found in either of those, it looks in the
174
	 * theme-compat folder last.
175
	 *
176
	 * @since 1.0.0
177
	 *
178
	 * @return mixed|void
179
	 */
180
	protected function get_template_paths() {
181
		$theme_directory = trailingslashit( $this->theme_template_directory );
182
183
		$file_paths = array(
184
			10  => trailingslashit( get_template_directory() ) . $theme_directory,
185
			100 => $this->get_templates_dir()
186
		);
187
188
		// Only add this conditionally, so non-child themes don't redundantly check active theme twice.
189
		if ( is_child_theme() ) {
190
			$file_paths[1] = trailingslashit( get_stylesheet_directory() ) . $theme_directory;
191
		}
192
193
		/**
194
		 * Allow ordered list of template paths to be amended.
195
		 *
196
		 * @since 1.0.0
197
		 *
198
		 * @param array $var Default is directory in child theme at index 1, parent theme at 10, and plugin at 100.
199
		 */
200
		$file_paths = apply_filters( $this->filter_prefix . '_template_paths', $file_paths );
201
202
		// sort the file paths based on priority
203
		ksort( $file_paths, SORT_NUMERIC );
204
205
		return array_map( 'trailingslashit', $file_paths );
206
	}
207
208
	/**
209
	 * Return the path to the templates directory in this plugin.
210
	 *
211
	 * May be overridden in subclass.
212
	 *
213
	 * @since 1.0.0
214
	 *
215
	 * @return string
216
	 */
217
	protected function get_templates_dir() {
218
		return trailingslashit( $this->plugin_directory ) . $this->plugin_template_directory;
219
	}
220
}
221