1 <?php
2 /**
3 * @package Joomla.Libraries
4 * @subpackage Plugin
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE.txt
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Plugin helper class
14 *
15 * @since 1.5
16 */
17 abstract class JPluginHelper
18 {
19 /**
20 * A persistent cache of the loaded plugins.
21 *
22 * @var array
23 * @since 1.7
24 */
25 protected static $plugins = null;
26
27 /**
28 * Get the path to a layout from a Plugin
29 *
30 * @param string $type Plugin type
31 * @param string $name Plugin name
32 * @param string $layout Layout name
33 *
34 * @return string Layout path
35 *
36 * @since 3.0
37 */
38 public static function getLayoutPath($type, $name, $layout = 'default')
39 {
40 $template = JFactory::getApplication()->getTemplate();
41 $defaultLayout = $layout;
42
43 if (strpos($layout, ':') !== false)
44 {
45 // Get the template and file name from the string
46 $temp = explode(':', $layout);
47 $template = $temp[0] === '_' ? $template : $temp[0];
48 $layout = $temp[1];
49 $defaultLayout = $temp[1] ?: 'default';
50 }
51
52 // Build the template and base path for the layout
53 $tPath = JPATH_THEMES . '/' . $template . '/html/plg_' . $type . '_' . $name . '/' . $layout . '.php';
54 $bPath = JPATH_PLUGINS . '/' . $type . '/' . $name . '/tmpl/' . $defaultLayout . '.php';
55 $dPath = JPATH_PLUGINS . '/' . $type . '/' . $name . '/tmpl/default.php';
56
57 // If the template has a layout override use it
58 if (file_exists($tPath))
59 {
60 return $tPath;
61 }
62 elseif (file_exists($bPath))
63 {
64 return $bPath;
65 }
66 else
67 {
68 return $dPath;
69 }
70 }
71
72 /**
73 * Get the plugin data of a specific type if no specific plugin is specified
74 * otherwise only the specific plugin data is returned.
75 *
76 * @param string $type The plugin type, relates to the subdirectory in the plugins directory.
77 * @param string $plugin The plugin name.
78 *
79 * @return mixed An array of plugin data objects, or a plugin data object.
80 *
81 * @since 1.5
82 */
83 public static function getPlugin($type, $plugin = null)
84 {
85 $result = array();
86 $plugins = static::load();
87
88 // Find the correct plugin(s) to return.
89 if (!$plugin)
90 {
91 foreach ($plugins as $p)
92 {
93 // Is this the right plugin?
94 if ($p->type === $type)
95 {
96 $result[] = $p;
97 }
98 }
99 }
100 else
101 {
102 foreach ($plugins as $p)
103 {
104 // Is this plugin in the right group?
105 if ($p->type === $type && $p->name === $plugin)
106 {
107 $result = $p;
108 break;
109 }
110 }
111 }
112
113 return $result;
114 }
115
116 /**
117 * Checks if a plugin is enabled.
118 *
119 * @param string $type The plugin type, relates to the subdirectory in the plugins directory.
120 * @param string $plugin The plugin name.
121 *
122 * @return boolean
123 *
124 * @since 1.5
125 */
126 public static function isEnabled($type, $plugin = null)
127 {
128 $result = static::getPlugin($type, $plugin);
129
130 return !empty($result);
131 }
132
133 /**
134 * Loads all the plugin files for a particular type if no specific plugin is specified
135 * otherwise only the specific plugin is loaded.
136 *
137 * @param string $type The plugin type, relates to the subdirectory in the plugins directory.
138 * @param string $plugin The plugin name.
139 * @param boolean $autocreate Autocreate the plugin.
140 * @param JEventDispatcher $dispatcher Optionally allows the plugin to use a different dispatcher.
141 *
142 * @return boolean True on success.
143 *
144 * @since 1.5
145 */
146 public static function importPlugin($type, $plugin = null, $autocreate = true, JEventDispatcher $dispatcher = null)
147 {
148 static $loaded = array();
149
150 // Check for the default args, if so we can optimise cheaply
151 $defaults = false;
152
153 if ($plugin === null && $autocreate === true && $dispatcher === null)
154 {
155 $defaults = true;
156 }
157
158 if (!$defaults || !isset($loaded[$type]))
159 {
160 $results = null;
161
162 // Load the plugins from the database.
163 $plugins = static::load();
164
165 // Get the specified plugin(s).
166 for ($i = 0, $t = count($plugins); $i < $t; $i++)
167 {
168 if ($plugins[$i]->type === $type && ($plugin === null || $plugins[$i]->name === $plugin))
169 {
170 static::import($plugins[$i], $autocreate, $dispatcher);
171 $results = true;
172 }
173 }
174
175 // Bail out early if we're not using default args
176 if (!$defaults)
177 {
178 return $results;
179 }
180
181 $loaded[$type] = $results;
182 }
183
184 return $loaded[$type];
185 }
186
187 /**
188 * Loads the plugin file.
189 *
190 * @param object $plugin The plugin.
191 * @param boolean $autocreate True to autocreate.
192 * @param JEventDispatcher $dispatcher Optionally allows the plugin to use a different dispatcher.
193 *
194 * @return void
195 *
196 * @since 1.5
197 * @deprecated 4.0 Use JPluginHelper::import() instead
198 */
199 protected static function _import($plugin, $autocreate = true, JEventDispatcher $dispatcher = null)
200 {
201 static::import($plugin, $autocreate, $dispatcher);
202 }
203
204 /**
205 * Loads the plugin file.
206 *
207 * @param object $plugin The plugin.
208 * @param boolean $autocreate True to autocreate.
209 * @param JEventDispatcher $dispatcher Optionally allows the plugin to use a different dispatcher.
210 *
211 * @return void
212 *
213 * @since 3.2
214 */
215 protected static function import($plugin, $autocreate = true, JEventDispatcher $dispatcher = null)
216 {
217 static $paths = array();
218
219 $plugin->type = preg_replace('/[^A-Z0-9_\.-]/i', '', $plugin->type);
220 $plugin->name = preg_replace('/[^A-Z0-9_\.-]/i', '', $plugin->name);
221
222 $path = JPATH_PLUGINS . '/' . $plugin->type . '/' . $plugin->name . '/' . $plugin->name . '.php';
223
224 if (!isset($paths[$path]))
225 {
226 if (file_exists($path))
227 {
228 if (!isset($paths[$path]))
229 {
230 require_once $path;
231 }
232
233 $paths[$path] = true;
234
235 if ($autocreate)
236 {
237 // Makes sure we have an event dispatcher
238 if (!is_object($dispatcher))
239 {
240 $dispatcher = JEventDispatcher::getInstance();
241 }
242
243 $className = 'Plg' . $plugin->type . $plugin->name;
244
245 if (class_exists($className))
246 {
247 // Load the plugin from the database.
248 if (!isset($plugin->params))
249 {
250 // Seems like this could just go bye bye completely
251 $plugin = static::getPlugin($plugin->type, $plugin->name);
252 }
253
254 // Instantiate and register the plugin.
255 new $className($dispatcher, (array) $plugin);
256 }
257 }
258 }
259 else
260 {
261 $paths[$path] = false;
262 }
263 }
264 }
265
266 /**
267 * Loads the published plugins.
268 *
269 * @return array An array of published plugins
270 *
271 * @since 1.5
272 * @deprecated 4.0 Use JPluginHelper::load() instead
273 */
274 protected static function _load()
275 {
276 return static::load();
277 }
278
279 /**
280 * Loads the published plugins.
281 *
282 * @return array An array of published plugins
283 *
284 * @since 3.2
285 */
286 protected static function load()
287 {
288 if (static::$plugins !== null)
289 {
290 return static::$plugins;
291 }
292
293 $levels = implode(',', JFactory::getUser()->getAuthorisedViewLevels());
294
295 /** @var JCacheControllerCallback $cache */
296 $cache = JFactory::getCache('com_plugins', 'callback');
297
298 $loader = function () use ($levels)
299 {
300 $db = JFactory::getDbo();
301 $query = $db->getQuery(true)
302 ->select(array($db->quoteName('folder', 'type'), $db->quoteName('element', 'name'), $db->quoteName('params')))
303 ->from('#__extensions')
304 ->where('enabled = 1')
305 ->where('type = ' . $db->quote('plugin'))
306 ->where('state IN (0,1)')
307 ->where('access IN (' . $levels . ')')
308 ->order('ordering');
309 $db->setQuery($query);
310
311 return $db->loadObjectList();
312 };
313
314 try
315 {
316 static::$plugins = $cache->get($loader, array(), md5($levels), false);
317 }
318 catch (JCacheException $cacheException)
319 {
320 static::$plugins = $loader();
321 }
322
323 return static::$plugins;
324 }
325 }
326