PageRenderTime 26ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/capsman/framework/classes/abstract/plugin.php

https://bitbucket.org/joelkriteman/argento
PHP | 473 lines | 239 code | 48 blank | 186 comment | 39 complexity | f37cc12ac79ea1b7ac89a97d6ec44294 MD5 | raw file
  1. <?php
  2. /**
  3. * Plugins related functions and classes.
  4. *
  5. * @version $Rev: 203758 $
  6. * @author Jordi Canals
  7. * @copyright Copyright (C) 2008, 2009, 2010 Jordi Canals
  8. * @license GNU General Public License version 2
  9. * @link http://alkivia.org
  10. * @package Alkivia
  11. * @subpackage Framework
  12. *
  13. Copyright 2008, 2009, 2010 Jordi Canals <devel@jcanals.cat>
  14. This program is free software; you can redistribute it and/or
  15. modify it under the terms of the GNU General Public License
  16. version 2 as published by the Free Software Foundation.
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. GNU General Public License for more details.
  21. You should have received a copy of the GNU General Public License
  22. along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. */
  24. require_once ( AK_CLASSES . '/abstract/module.php' );
  25. /**
  26. * Abtract class to be used as a plugin template.
  27. * Must be implemented before using this class and it's recommended to prefix the class to prevent collissions.
  28. * There are some special functions that have to be declared in implementations to perform main actions:
  29. * - pluginActivate (Protected) Actions to run when activating the plugin.
  30. * - pluginDeactivate (Protected) Actions to run when deactivating the plugin.
  31. * - pluginUpdate (Protected) Actions to update the plugin to a new version. (Updating version on DB is done after this).
  32. * Takes plugin running version as a parameter.
  33. * - pluginsLoaded (Protected) Runs at 'plugins_loaded' action hook.
  34. * - registerWidgets (Protected) Runs at 'widgets_init' action hook.
  35. *
  36. * @author Jordi Canals
  37. * @package Alkivia
  38. * @subpackage Framework
  39. * @link http://wiki.alkivia.org/framework/classes/plugin
  40. */
  41. abstract class akPluginAbstract extends akModuleAbstract
  42. {
  43. /**
  44. * Holds the installed and active components.
  45. * @var array
  46. */
  47. private $components = false;
  48. /**
  49. * Class constructor.
  50. * Calls the implementated method 'startUp' if it exists. This is done at plugins loading time.
  51. * Prepares admin menus by seting an action for the implemented method '_adminMenus' if it exists.
  52. *
  53. * @param string $mod_file Full main plugin's filename (absolute to root).
  54. * @param string $ID Plugin short name (known as plugin ID).
  55. * @return spostsPlugin|false The plugin object or false if not compatible.
  56. */
  57. public function __construct( $mod_file, $ID = '' )
  58. {
  59. parent::__construct('plugin', $ID, $mod_file);
  60. if ( $this->isCompatible() ) {
  61. // Activation and deactivation hooks.
  62. register_activation_hook($this->mod_file, array($this, 'activate'));
  63. register_deactivation_hook($this->mod_file, array($this, 'deactivate'));
  64. add_action('plugins_loaded', array($this, 'init'));
  65. }
  66. }
  67. /**
  68. * Fires on plugin activation.
  69. * @return void
  70. */
  71. protected function pluginActivate () {}
  72. /**
  73. * Fires on plugin deactivation.
  74. * @return void
  75. */
  76. protected function pluginDeactivate () {}
  77. /**
  78. * Updates the plugin to a new version.
  79. * @param string $version Old plugin version.
  80. * @return void
  81. */
  82. protected function pluginUpdate ( $version ) {}
  83. /**
  84. * Fires when plugins have been loaded.
  85. * @return void
  86. */
  87. protected function pluginsLoaded () {}
  88. /**
  89. * Fires on Widgets init.
  90. * @return void
  91. */
  92. protected function registerWidgets () {}
  93. /**
  94. * Allows to check if plugin is ready to load components on implementations.
  95. * Overwrite this method and return true to load components, false to omit components load.
  96. *
  97. * @return boolean If components can be loaded or not.
  98. */
  99. protected function readyForComponents ()
  100. {
  101. return false;
  102. }
  103. /**
  104. * Activates the plugin. Only runs on first activation.
  105. * Saves the plugin version in DB, and calls the 'pluginActivate' method.
  106. *
  107. * @uses do_action() Calls 'ak_activate_<modID>_plugin' action hook.
  108. * @hook register_activation_hook
  109. * @access private
  110. * @return void
  111. */
  112. final function activate()
  113. {
  114. $this->pluginActivate();
  115. // Save options and version
  116. $this->cfg->saveOptions($this->ID);
  117. add_option($this->ID . '_version', $this->version);
  118. // Load and activate plugin components.
  119. $this->components = ak_get_installed_components($this->componentsPath(), true);
  120. if ( empty($this->components) ) {
  121. $this->components = false;
  122. } else {
  123. foreach ( $this->components as $id => $component ) {
  124. if ( $component['Core'] ) {
  125. require_once( $component['File'] );
  126. do_action('ak_activate_' . $this->ID . '_' . $id);
  127. $this->components[$id]['active'] = 1;
  128. } else {
  129. $this->components[$id]['active'] = 0;
  130. }
  131. }
  132. update_option($this->ID . '_components', $this->components);
  133. }
  134. // Do activated hook.
  135. do_action('ak_activate_' . $this->ID . '_plugin');
  136. }
  137. /**
  138. * Deactivates the plugin.
  139. *
  140. * @uses do_action() Calls 'ak_deactivate_<modID>_plugin' action hook.
  141. * @hook register_deactivation_hook
  142. * @access private
  143. * @return void
  144. */
  145. final function deactivate()
  146. {
  147. $this->pluginDeactivate();
  148. do_action('ak_deactivate_' . $this->ID . '_plugin');
  149. }
  150. /**
  151. * Init the plugin (In action 'plugins_loaded')
  152. * Here whe call the 'pluginUpdate' and 'pluginsLoaded' methods.
  153. * Also the plugin version and settings are updated here.
  154. *
  155. * @hook action plugins_loaded
  156. * @uses do_action() Calls the 'ak_<modID>_updated' action hook.
  157. *
  158. * @access private
  159. * @return void
  160. */
  161. final function init()
  162. {
  163. // First, check if the plugin needs to be updated.
  164. if ( $this->needs_update ) {
  165. $version = get_option($this->ID . '_version');
  166. $this->pluginUpdate($version);
  167. $this->cfg->saveOptions($this->ID);
  168. update_option($this->ID . '_version', $this->version);
  169. $this->searchNewComponents();
  170. do_action('ak_' . $this->ID . '_updated');
  171. }
  172. $this->pluginsLoaded();
  173. $this->loadComponents();
  174. }
  175. /**
  176. * Loads plugin components if found.
  177. *
  178. * @return void
  179. */
  180. final function loadComponents()
  181. {
  182. if ( ! $this->readyForComponents() ) {
  183. return;
  184. }
  185. $this->components = get_option($this->ID . '_components');
  186. if ( ! is_array($this->components) ) {
  187. return;
  188. }
  189. foreach ( $this->components as $component ) {
  190. if ( $component['active'] ) {
  191. require_once ( $component['File']);
  192. }
  193. }
  194. do_action('ak_' . $this->ID . '_components_init');
  195. }
  196. /**
  197. * Reloads and updates installed components.
  198. * If a new core component is found, it will be activated automatically.
  199. *
  200. * @return void
  201. */
  202. private function searchNewComponents ()
  203. {
  204. $components = ak_get_installed_components($this->componentsPath(), true);
  205. if ( empty($components) ) {
  206. $this->components = false;
  207. return;
  208. }
  209. $installed = array();
  210. $core = array();
  211. $optional = array();
  212. // Sort components by core and optional. Then by name.
  213. foreach ( $components as $id => $component ) {
  214. if ( $component['Core'] ) {
  215. $core[$id] = $component;
  216. } else {
  217. $optional[$id] = $component;
  218. }
  219. }
  220. ksort($core); ksort($optional); // Sort components by ID.
  221. $components = array_merge($core, $optional);
  222. // Now, activate new core components, and set activation for optional.
  223. $this->components = get_option($this->ID . '_components');
  224. foreach ( $components as $id => $component ) {
  225. $installed[$id] = $component;
  226. if ( $component['Core'] ) {
  227. $installed[$id]['active'] = 1;
  228. if ( ! isset($this->components[$id]) || ! $this->components[$id]['active'] ) {
  229. require_once( $component['File']);
  230. do_action('ak_activate_' . $this->ID . '_' . $id);
  231. }
  232. } else {
  233. if ( isset($this->components[$id]['active']) ) {
  234. $installed[$id]['active'] = $this->components[$id]['active'];
  235. } else {
  236. $installed[$id]['active'] = 0;
  237. }
  238. }
  239. }
  240. $this->components = $installed;
  241. update_option($this->ID . '_components', $this->components);
  242. }
  243. /**
  244. * Checks if a component is installed and active.
  245. *
  246. * @return boolean If the component is active or not.
  247. */
  248. public function activeComponent ( $name )
  249. {
  250. if ( ! is_array($this->components) ) {
  251. return false;
  252. }
  253. $name = strtolower($name);
  254. if ( isset($this->components[$name]) && $this->components[$name]['active'] ) {
  255. return true;
  256. } else {
  257. return false;
  258. }
  259. }
  260. /**
  261. * Inits the widgets (In action 'widgets_init')
  262. * Before loading the widgets, we check that standard sidebar is present.
  263. *
  264. * @hook action 'widgets_init'
  265. * @return void
  266. */
  267. final function widgetsInit()
  268. {
  269. if ( class_exists('WP_Widget') && function_exists('register_widget') && function_exists('unregister_widget') ) {
  270. $this->registerWidgets();
  271. do_action('ak_' . $this->ID . '_widgets_init');
  272. } else {
  273. add_action('admin_notices', array($this, 'noSidebarWarning'));
  274. }
  275. }
  276. /**
  277. * Checks if the plugin is compatible with the current WordPress version.
  278. * If it's not compatible, sets an admin warning.
  279. *
  280. * @return boolean Plugin is compatible with this WordPress version or not.
  281. */
  282. final public function isCompatible()
  283. {
  284. global $wp_version;
  285. if ( version_compare($wp_version, $this->mod_data['Requires'] , '>=') ) {
  286. return true;
  287. } elseif ( ! has_action('admin_notices', array($this, 'noCompatibleWarning')) ) {
  288. add_action('admin_notices', array($this, 'noCompatibleWarning'));
  289. }
  290. return false;
  291. }
  292. /**
  293. * Shows a warning message when the plugin is not compatible with current WordPress version.
  294. * This is used by calling the action 'admin_notices' in isCompatible()
  295. *
  296. * @hook action admin_notices
  297. * @access private
  298. * @return void
  299. */
  300. final function noCompatibleWarning()
  301. {
  302. $this->loadTranslations(); // We have not loaded translations yet.
  303. echo '<div class="error"><p><strong>' . __('Warning:', 'akfw') . '</strong> '
  304. . sprintf(__('The active plugin %s is not compatible with your WordPress version.', 'akfw'),
  305. '&laquo;' . $this->mod_data['Name'] . ' ' . $this->version . '&raquo;')
  306. . '</p><p>' . sprintf(__('WordPress %s is required to run this plugin.', 'akfw'), $this->mod_data['Requires'])
  307. . '</p></div>';
  308. }
  309. /**
  310. * Shows an admin warning when not using the WordPress standard sidebar.
  311. * This is done by calling the action 'admin_notices' in isStandardSidebar()
  312. *
  313. * @hook action admin_notices
  314. * @access private
  315. * @return void
  316. */
  317. final function noSidebarWarning()
  318. {
  319. $this->loadTranslations(); // We have not loaded translations yet.
  320. echo '<div class="error"><p><strong>' . __('Warning:', $this->ID) . '</strong> '
  321. . __('Standard sidebar functions are not present.', $this->ID) . '</p><p>'
  322. . sprintf(__('It is required to use the standard sidebar to run %s', $this->ID),
  323. '&laquo;' . $this->mod_data['Name'] . ' ' . $this->version . '&raquo;')
  324. . '</p></div>';
  325. }
  326. /**
  327. * Loads plugins data.
  328. *
  329. * @return void
  330. */
  331. final protected function loadData()
  332. {
  333. if ( empty($this->mod_data) ) {
  334. if ( ! function_exists('get_plugin_data') ) {
  335. require_once ( ABSPATH . 'wp-admin/includes/plugin.php' );
  336. }
  337. $plugin_data = get_plugin_data($this->mod_file);
  338. $readme_data = ak_module_readme_data($this->mod_file);
  339. $this->mod_data = array_merge($readme_data, $plugin_data);
  340. $this->version = $this->mod_data['Version'];
  341. }
  342. }
  343. /**
  344. * Returns the path to plugin components.
  345. *
  346. * @uses apply_filters() Applies the ak_<plugin>_components_path filter on default path.
  347. * @return string Path to components directory.
  348. */
  349. final protected function componentsPath ()
  350. {
  351. $path = dirname($this->mod_file) . '/components';
  352. return apply_filters('ak_' . $this->ID . '_components_path', $path);
  353. }
  354. /**
  355. * Form part to activate/deactivate plugin components.
  356. * To be included on other configuration or settings form.
  357. * String for component name and description have to be included on plugin text_domain.
  358. *
  359. * @return void
  360. */
  361. final protected function componentActivationForm ()
  362. {
  363. if ( $this->getOption('disable-components-activation') ) {
  364. return;
  365. }
  366. $this->searchNewComponents();
  367. ?>
  368. <dl>
  369. <dt><?php _e('Activate Components', 'akfw'); ?></dt>
  370. <dd>
  371. <?php wp_nonce_field('ak-component-activation', '_aknonce', false); ?>
  372. <table width="100%" class="form-table">
  373. <?php foreach ( $this->components as $c) :
  374. if ( ! $c['Core'] ) : ?>
  375. <tr>
  376. <th scope="row"><?php _e($c['Name'], $this->ID) ?>:</th>
  377. <td>
  378. <input type="radio" name="components[<?php echo $c['Component']; ?>]" value="1" <?php checked(1, $c['active']); ?> /> <?php _e('Yes', 'akfw'); ?> &nbsp;&nbsp;
  379. <input type="radio" name="components[<?php echo $c['Component']; ?>]" value="0" <?php checked(0, $c['active']); ?> /> <?php _e('No', 'akfw'); ?> &nbsp;&nbsp;
  380. <span class="setting-description"><?php _e($c['Description'], $this->ID); ?></span>
  381. </td>
  382. </tr>
  383. <?php endif;
  384. endforeach; ?>
  385. </table>
  386. </dd>
  387. </dl>
  388. <?php
  389. }
  390. /**
  391. * Saves data from componets activation form.
  392. * Activates or deactivates components as requested by user.
  393. *
  394. * @return void
  395. */
  396. final protected function saveActivationForm ()
  397. {
  398. if ( $this->getOption('disable-components-activation') ) {
  399. return;
  400. }
  401. check_admin_referer('ak-component-activation', '_aknonce');
  402. if ( isset($_POST['action']) && 'update' == $_POST['action'] ) {
  403. $post = stripslashes_deep($_POST['components'] );
  404. $this->components = get_option($this->ID . '_components');
  405. $this->searchNewComponents();
  406. foreach ( $post as $name => $activate ) {
  407. if ( $activate && ! $this->components[$name]['active'] ) {
  408. require_once( $this->components[$name]['File']);
  409. do_action('ak_activate_' . $this->ID . '_' . $name);
  410. } elseif ( ! $activate && $this->components[$name]['active'] ) {
  411. require_once( $this->components[$name]['File']);
  412. do_action('ak_deactivate_' . $this->ID . '_' . $name);
  413. }
  414. $this->components[$name]['active'] = $activate;
  415. }
  416. update_option($this->ID . '_components', $this->components);
  417. } else {
  418. wp_die('Bad form received.', $this->ID);
  419. }
  420. }
  421. }