PageRenderTime 68ms CodeModel.GetById 37ms RepoModel.GetById 1ms app.codeStats 0ms

/frog/app/models/Plugin.php

https://github.com/Doap/FrogCMS
PHP | 422 lines | 225 code | 66 blank | 131 comment | 52 complexity | 851533ded167638915dadcef4884c88c MD5 | raw file
  1. <?php
  2. /**
  3. * Frog CMS - Content Management Simplified. <http://www.madebyfrog.com>
  4. * Copyright (C) 2008 Philippe Archambault <philippe.archambault@gmail.com>
  5. * Copyright (C) 2008 Martijn van der Kleijn <martijn.niji@gmail.com>
  6. *
  7. * This file is part of Frog CMS.
  8. *
  9. * Frog CMS is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * Frog CMS is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with Frog CMS. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * Frog CMS has made an exception to the GNU General Public License for plugins.
  23. * See exception.txt for details and the full text.
  24. */
  25. /**
  26. * @package frog
  27. * @subpackage models
  28. *
  29. * @author Philippe Archambault <philippe.archambault@gmail.com>
  30. * @author Martijn van der Kleijn <martijn.niji@gmail.com>
  31. * @version 0.9.5
  32. * @license http://www.gnu.org/licenses/gpl.html GPL License
  33. * @copyright Philippe Archambault, Martijn van der Kleijn 2008
  34. */
  35. /**
  36. * class Plugin
  37. *
  38. * Provide a Plugin API to make frog more flexible
  39. *
  40. * @author Philippe Archambault <philippe.archambault@gmail.com>
  41. * @since Frog version 0.9
  42. */
  43. class Plugin
  44. {
  45. static $plugins = array();
  46. static $plugins_infos = array();
  47. static $updatefile_cache = array();
  48. static $controllers = array();
  49. static $javascripts = array();
  50. /**
  51. * Initialize all activated plugin by including is index.php file
  52. */
  53. static function init()
  54. {
  55. self::$plugins = unserialize(Setting::get('plugins'));
  56. foreach (self::$plugins as $plugin_id => $tmp)
  57. {
  58. $file = CORE_ROOT.'/plugins/'.$plugin_id.'/index.php';
  59. if (file_exists($file))
  60. include $file;
  61. $file = CORE_ROOT.'/plugins/'.$plugin_id.'/i18n/'.I18n::getLocale().'-message.php';
  62. if (file_exists($file))
  63. {
  64. $array = include $file;
  65. I18n::add($array);
  66. }
  67. }
  68. }
  69. /**
  70. * Set plugin informations (id, title, description, version and website)
  71. *
  72. * @param infos array Assoc array with plugin informations
  73. */
  74. static function setInfos($infos)
  75. {
  76. self::$plugins_infos[$infos['id']] = (object) $infos;
  77. }
  78. /**
  79. * Activate a plugin. This will execute the enable.php file of the plugin
  80. * when found.
  81. *
  82. * @param plugin_id string The plugin name to activate
  83. */
  84. static function activate($plugin_id)
  85. {
  86. self::$plugins[$plugin_id] = 1;
  87. self::save();
  88. $file = CORE_ROOT.'/plugins/'.$plugin_id.'/enable.php';
  89. if (file_exists($file))
  90. include $file;
  91. $class_name = Inflector::camelize($plugin_id).'Controller';
  92. AutoLoader::addFile($class_name, self::$controllers[$plugin_id]->file);
  93. }
  94. /**
  95. * Deactivate a plugin
  96. *
  97. * @param plugin_id string The plugin name to deactivate
  98. */
  99. static function deactivate($plugin_id)
  100. {
  101. if (isset(self::$plugins[$plugin_id]))
  102. {
  103. unset(self::$plugins[$plugin_id]);
  104. self::save();
  105. $file = CORE_ROOT.'/plugins/'.$plugin_id.'/disable.php';
  106. if (file_exists($file))
  107. include $file;
  108. }
  109. }
  110. /**
  111. * Save activated plugins to the setting 'plugins'
  112. */
  113. static function save()
  114. {
  115. Setting::saveFromData(array('plugins' => serialize(self::$plugins)));
  116. }
  117. /**
  118. * Find all plugins installed in the plugin folder
  119. *
  120. * @return array
  121. */
  122. static function findAll()
  123. {
  124. $dir = CORE_ROOT.'/plugins/';
  125. if ($handle = opendir($dir))
  126. {
  127. while (false !== ($plugin_id = readdir($handle)))
  128. {
  129. if ( ! isset(self::$plugins[$plugin_id]) && is_dir($dir.$plugin_id) && strpos($plugin_id, '.') !== 0)
  130. {
  131. $file = CORE_ROOT.'/plugins/'.$plugin_id.'/index.php';
  132. if (file_exists($file))
  133. include $file;
  134. }
  135. }
  136. closedir($handle);
  137. }
  138. ksort(self::$plugins_infos);
  139. return self::$plugins_infos;
  140. }
  141. /**
  142. * Check the file mentioned as update_url for the latest plugin version available.
  143. * Messages that can be returned:
  144. * unknown - returned if the plugin doesn't provide an update url
  145. * latest - returned if the plugin version matches the version number registerd at the url
  146. * error - returned if the update url could not be reached or for any other reason
  147. *
  148. * @param plugin object A plugin object.
  149. *
  150. * @return string The latest version number or a localized message.
  151. */
  152. static function checkLatest($plugin)
  153. {
  154. $data = null;
  155. if (!defined('CHECK_UPDATES') || !CHECK_UPDATES)
  156. return __('unknown');
  157. // Check if plugin has update file url set
  158. if ( ! isset($plugin->update_url) )
  159. return __('unknown');
  160. // Check if update file was already cached and is no older than 30 minutes
  161. if (array_key_exists($plugin->update_url, Plugin::$updatefile_cache) && (Plugin::$updatefile_cache[$plugin->update_url]['time'] + 30 * 60) < time()) {
  162. unset(Plugin::$updatefile_cache[$plugin->update_url]);
  163. }
  164. if (!array_key_exists($plugin->update_url, Plugin::$updatefile_cache)) {
  165. // Read and cache the update file
  166. if (!defined('CHECK_TIMEOUT')) define('CHECK_TIMEOUT', 5);
  167. $ctx = stream_context_create(array('http' => array('timeout' => CHECK_TIMEOUT)));
  168. if ( ! $data = file_get_contents($plugin->update_url, 0, $ctx)) {
  169. return __('error');
  170. }
  171. Plugin::$updatefile_cache[$plugin->update_url] = array('time' => time(), 'data' => $data);
  172. }
  173. $xml = simplexml_load_string(Plugin::$updatefile_cache[$plugin->update_url]['data']);
  174. foreach($xml as $node) {
  175. if ($plugin->id == $node->id)
  176. if ($plugin->version == $node->version)
  177. return __('latest');
  178. else
  179. return (string) $node->version;
  180. }
  181. return __('error');
  182. }
  183. /**
  184. * Add a controller (tab) to the administration
  185. *
  186. * @param plugin_id string The folder name of the plugin
  187. * @param label string The tab label
  188. * @param permissions string List of roles that will have the tab displayed
  189. * separate by coma ie: 'administrator,developer'
  190. * @param show_tab boolean Either 'true' or 'false'. Defaults to true.
  191. *
  192. * @return void
  193. */
  194. static function addController($plugin_id, $label, $permissions=false, $show_tab=true)
  195. {
  196. $class_name = Inflector::camelize($plugin_id).'Controller';
  197. self::$controllers[$plugin_id] = (object) array(
  198. 'label' => ucfirst($label),
  199. 'class_name' => $class_name,
  200. 'file' => CORE_ROOT.'/plugins/'.$plugin_id.'/'.$class_name.'.php',
  201. 'permissions' => $permissions,
  202. 'show_tab' => $show_tab
  203. );
  204. AutoLoader::addFile($class_name, self::$controllers[$plugin_id]->file);
  205. }
  206. /**
  207. * Add a javascript file to be added to the html page for a plugin.
  208. * Backend only right now.
  209. *
  210. * @param $plugin_id string The folder name of the plugin
  211. * @param $file string The path to the javascript file relative to plugin root
  212. */
  213. static function addJavascript($plugin_id, $file)
  214. {
  215. if (file_exists(CORE_ROOT . '/plugins/' . $plugin_id . '/' . $file))
  216. {
  217. self::$javascripts[] = $plugin_id.'/'.$file;
  218. }
  219. }
  220. static function hasSettingsPage($plugin_id)
  221. {
  222. $class_name = Inflector::camelize($plugin_id).'Controller';
  223. return (array_key_exists($plugin_id, Plugin::$controllers) && method_exists($class_name, 'settings'));
  224. }
  225. static function hasDocumentationPage($plugin_id)
  226. {
  227. $class_name = Inflector::camelize($plugin_id).'Controller';
  228. return (array_key_exists($plugin_id, Plugin::$controllers) && method_exists($class_name, 'documentation'));
  229. }
  230. /**
  231. * Returns true if a plugin is enabled for use.
  232. *
  233. * @param string $plugin_id
  234. */
  235. static function isEnabled($plugin_id)
  236. {
  237. if (array_key_exists($plugin_id, Plugin::$plugins) && Plugin::$plugins[$plugin_id] == 1)
  238. return true;
  239. else
  240. return 0;
  241. }
  242. /**
  243. * Stores all settings from a name<->value pair array in the database.
  244. *
  245. * @param array $settings Array of name-value pairs
  246. * @param string $plugin_id The folder name of the plugin
  247. */
  248. static function setAllSettings($array=null, $plugin_id=null)
  249. {
  250. if ($array == null || $plugin_id == null) return false;
  251. global $__FROG_CONN__;
  252. $tablename = TABLE_PREFIX.'plugin_settings';
  253. $plugin_id = $__FROG_CONN__->quote($plugin_id);
  254. $existingSettings = array();
  255. $sql = "SELECT name FROM $tablename WHERE plugin_id=$plugin_id";
  256. $stmt = $__FROG_CONN__->prepare($sql);
  257. $stmt->execute();
  258. while ($settingname = $stmt->fetchColumn())
  259. $existingSettings[$settingname] = $settingname;
  260. $ret = false;
  261. foreach ($array as $name => $value)
  262. {
  263. if (array_key_exists($name, $existingSettings))
  264. {
  265. $name = $__FROG_CONN__->quote($name);
  266. $value = $__FROG_CONN__->quote($value);
  267. $sql = "UPDATE $tablename SET value=$value WHERE name=$name AND plugin_id=$plugin_id";
  268. }
  269. else
  270. {
  271. $name = $__FROG_CONN__->quote($name);
  272. $value = $__FROG_CONN__->quote($value);
  273. $sql = "INSERT INTO $tablename (value, name, plugin_id) VALUES ($value, $name, $plugin_id)";
  274. }
  275. $stmt = $__FROG_CONN__->prepare($sql);
  276. $ret = $stmt->execute();
  277. }
  278. return $ret;
  279. }
  280. /**
  281. * Allows you to store a single setting in the database.
  282. *
  283. * @param string $name Setting name
  284. * @param string $value Setting value
  285. * @param string $plugin_id Plugin folder name
  286. */
  287. static function setSetting($name=null, $value=null, $plugin_id=null)
  288. {
  289. if ($name == null || $value == null || $plugin_id == null) return false;
  290. global $__FROG_CONN__;
  291. $tablename = TABLE_PREFIX.'plugin_settings';
  292. $plugin_id = $__FROG_CONN__->quote($plugin_id);
  293. $existingSettings = array();
  294. $sql = "SELECT name FROM $tablename WHERE plugin_id=$plugin_id";
  295. $stmt = $__FROG_CONN__->prepare($sql);
  296. $stmt->execute(array($plugin_id));
  297. while ($settingname = $stmt->fetchColumn())
  298. $existingSettings[$settingname] = $settingname;
  299. if (in_array($name, $existingSettings))
  300. {
  301. $name = $__FROG_CONN__->quote($name);
  302. $value = $__FROG_CONN__->quote($value);
  303. $sql = "UPDATE $tablename SET value=$value WHERE name=$name AND plugin_id=$plugin_id";
  304. }
  305. else
  306. {
  307. $name = $__FROG_CONN__->quote($name);
  308. $value = $__FROG_CONN__->quote($value);
  309. $sql = "INSERT INTO $tablename (value, name, plugin_id) VALUES ($value, $name, $plugin_id)";
  310. }
  311. $stmt = $__FROG_CONN__->prepare($sql);
  312. $stmt->execute();
  313. }
  314. /**
  315. * Retrieves all settings for a plugin and returns an array of name-value pairs.
  316. * Returns empty array when unsuccessful in retrieving the settings.
  317. *
  318. * @param <type> $plugin_id
  319. */
  320. static function getAllSettings($plugin_id=null)
  321. {
  322. if ($plugin_id == null) return false;
  323. global $__FROG_CONN__;
  324. $tablename = TABLE_PREFIX.'plugin_settings';
  325. $plugin_id = $__FROG_CONN__->quote($plugin_id);
  326. $settings = array();
  327. $sql = "SELECT name,value FROM $tablename WHERE plugin_id=$plugin_id";
  328. $stmt = $__FROG_CONN__->prepare($sql);
  329. $stmt->execute();
  330. while ($obj = $stmt->fetchObject()) {
  331. $settings[$obj->name] = $obj->value;
  332. }
  333. return $settings;
  334. }
  335. /**
  336. * Returns the value for a specified setting.
  337. * Returns false when unsuccessful in retrieving the setting.
  338. *
  339. * @param <type> $name
  340. * @param <type> $plugin_id
  341. */
  342. static function getSetting($name=null, $plugin_id=null)
  343. {
  344. if ($name == null || $plugin_id == null) return false;
  345. global $__FROG_CONN__;
  346. $tablename = TABLE_PREFIX.'plugin_settings';
  347. $plugin_id = $__FROG_CONN__->quote($plugin_id);
  348. $name = $__FROG_CONN__->quote($name);
  349. $existingSettings = array();
  350. $sql = "SELECT value FROM $tablename WHERE plugin_id=$plugin_id AND name=$name LIMIT 1";
  351. $stmt = $__FROG_CONN__->prepare($sql);
  352. $stmt->execute();
  353. if ($value = $stmt->fetchColumn()) return $value;
  354. else return false;
  355. }
  356. } // end Plugin class