PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/admin-menu-editor/includes/shadow_plugin_framework.php

https://github.com/ChildsD/Chemistry
PHP | 356 lines | 182 code | 51 blank | 123 comment | 49 complexity | 758c2636c925da7502c24889bad39899 MD5 | raw file
  1. <?php
  2. /**
  3. * @author W-Shadow
  4. * @copyright 2008-2011
  5. */
  6. //Make sure the needed constants are defined
  7. if ( ! defined( 'WP_CONTENT_URL' ) )
  8. define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' );
  9. if ( ! defined( 'WP_CONTENT_DIR' ) )
  10. define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
  11. if ( ! defined( 'WP_PLUGIN_URL' ) )
  12. define( 'WP_PLUGIN_URL', WP_CONTENT_URL. '/plugins' );
  13. if ( ! defined( 'WP_PLUGIN_DIR' ) )
  14. define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );
  15. //Load JSON functions for PHP < 5.2
  16. if ( !(function_exists('json_encode') && function_exists('json_decode')) && !(class_exists('Services_JSON') || class_exists('Moxiecode_JSON')) ){
  17. $class_json_path = ABSPATH.WPINC.'/class-json.php';
  18. $class_moxiecode_json_path = ABSPATH.WPINC.'/js/tinymce/plugins/spellchecker/classes/utils/JSON.php';
  19. if ( file_exists($class_json_path) ){
  20. require $class_json_path;
  21. } elseif ( file_exists($class_moxiecode_json_path) ) {
  22. require $class_moxiecode_json_path;
  23. }
  24. }
  25. class MenuEd_ShadowPluginFramework {
  26. public static $framework_version = '0.4.1';
  27. public $is_mu_plugin = null; //True if installed in the mu-plugins directory, false otherwise
  28. protected $options = array();
  29. public $option_name = ''; //should be set or overriden by the plugin
  30. protected $defaults = array(); //should be set or overriden by the plugin
  31. protected $sitewide_options = false; //WPMU only : save the setting in a site-wide option
  32. protected $serialize_with_json = false; //Use the JSON format for option storage
  33. public $plugin_file = ''; //Filename of the plugin.
  34. public $plugin_basename = ''; //Basename of the plugin, as returned by plugin_basename().
  35. public $plugin_dir_url = ''; //The URL of the plugin's folder
  36. protected $magic_hooks = false; //Automagically set up hooks for all methods named "hook_[hookname]" .
  37. protected $magic_hook_priority = 10; //Priority for magically set hooks.
  38. protected $settings_link = ''; //If set, this will be automatically added after "Deactivate"/"Edit".
  39. /**
  40. * Class constructor. Populates some internal fields, then calls the plugin's own
  41. * intializer (if any).
  42. *
  43. * @param string $plugin_file Plugin's filename. Usuallly you can just use __FILE__.
  44. * @return void
  45. */
  46. function __construct( $plugin_file = '', $option_name = null ){
  47. if ($plugin_file == ''){
  48. //Try to guess the name of the file that included this file.
  49. //Not implemented yet.
  50. }
  51. $this->option_name = $option_name;
  52. if ( is_null($this->is_mu_plugin) )
  53. $this->is_mu_plugin = $this->is_in_wpmu_plugin_dir($plugin_file);
  54. $this->plugin_file = $plugin_file;
  55. $this->plugin_basename = plugin_basename($this->plugin_file);
  56. if ( $this->is_mu_plugin ){
  57. $this->plugin_dir_url = WPMU_PLUGIN_URL . '/' . dirname($this->plugin_basename);
  58. } else {
  59. $this->plugin_dir_url = WP_PLUGIN_URL . '/' . dirname($this->plugin_basename);
  60. }
  61. /************************************
  62. Add the default hooks
  63. ************************************/
  64. add_action('activate_'.$this->plugin_basename, array(&$this,'activate'));
  65. add_action('deactivate_'.$this->plugin_basename, array(&$this,'deactivate'));
  66. $this->init(); //Call the plugin's init() function
  67. $this->init_finish(); //Complete initialization by loading settings, etc
  68. }
  69. /**
  70. * Init the plugin. Should be overridden in a sub-class.
  71. * Called by the class constructor.
  72. *
  73. * @return void
  74. */
  75. function init(){
  76. //Do nothing.
  77. }
  78. /**
  79. * Initialize settings and set up magic hooks.
  80. *
  81. * @return void
  82. */
  83. function init_finish(){
  84. /************************************
  85. Load settings
  86. ************************************/
  87. //The provided $option_name overrides the default only if it is set to something useful
  88. if ( $this->option_name == '' ) {
  89. //Generate a unique name
  90. $this->option_name = 'plugin_'.md5($this->plugin_basename);
  91. }
  92. //Do we need to load the plugin's settings?
  93. if ($this->option_name != null){
  94. $this->load_options();
  95. }
  96. //Add a "Settings" action link
  97. if ($this->settings_link)
  98. add_filter('plugin_action_links', array(&$this, 'plugin_action_links'), 10, 2);
  99. if ($this->magic_hooks)
  100. $this->set_magic_hooks();
  101. }
  102. /**
  103. * Load the plugin's configuration.
  104. * Loads the specified option into $this->options, substituting defaults where necessary.
  105. *
  106. * @param string $option_name Optional. The slug of the option to load. If not set, the value of $this->option_name will be used instead.
  107. * @return boolean TRUE if options were loaded okay and FALSE otherwise.
  108. */
  109. function load_options($option_name = null){
  110. if ( empty($option_name) ){
  111. $option_name = $this->option_name;
  112. }
  113. if ( $this->sitewide_options ) {
  114. $this->options = get_site_option($option_name);
  115. } else {
  116. $this->options = get_option($option_name);
  117. }
  118. if ( $this->serialize_with_json || is_string($this->options) ){
  119. $this->options = $this->json_decode($this->options, true);
  120. }
  121. if(!is_array($this->options)){
  122. $this->options = $this->defaults;
  123. return false;
  124. } else {
  125. $this->options = array_merge($this->defaults, $this->options);
  126. return true;
  127. }
  128. }
  129. /**
  130. * ShadowPluginFramework::save_options()
  131. * Saves the $options array to the database.
  132. *
  133. * @return void
  134. */
  135. function save_options(){
  136. if ($this->option_name) {
  137. $stored_options = $this->options;
  138. if ( $this->serialize_with_json ){
  139. $stored_options = $this->json_encode($stored_options);
  140. }
  141. if ( $this->sitewide_options ) {
  142. update_site_option($this->option_name, $stored_options);
  143. } else {
  144. update_option($this->option_name, $stored_options);
  145. }
  146. }
  147. }
  148. /**
  149. * Backwards fompatible json_decode.
  150. *
  151. * @param string $data
  152. * @param bool $assoc Decode objects as associative arrays.
  153. * @return string
  154. */
  155. function json_decode($data, $assoc=false){
  156. if ( function_exists('json_decode') ){
  157. return json_decode($data, $assoc);
  158. }
  159. if ( class_exists('Services_JSON') ){
  160. $flag = $assoc?SERVICES_JSON_LOOSE_TYPE:0;
  161. $json = new Services_JSON($flag);
  162. return( $json->decode($data) );
  163. } elseif ( class_exists('Moxiecode_JSON') ){
  164. $json = new Moxiecode_JSON();
  165. return $json->decode($data);
  166. } else {
  167. trigger_error('No JSON parser available', E_USER_ERROR);
  168. }
  169. }
  170. /**
  171. * Backwards fompatible json_encode.
  172. *
  173. * @param mixed $data
  174. * @return string
  175. */
  176. function json_encode($data) {
  177. if ( function_exists('json_encode') ){
  178. return json_encode($data);
  179. }
  180. if ( class_exists('Services_JSON') ){
  181. $json = new Services_JSON();
  182. return( $json->encodeUnsafe($data) );
  183. } elseif ( class_exists('Moxiecode_JSON') ){
  184. $json = new Moxiecode_JSON();
  185. return $json->encode($data);
  186. } else {
  187. trigger_error('No JSON parser available', E_USER_ERROR);
  188. }
  189. }
  190. /**
  191. * ShadowPluginFramework::set_magic_hooks()
  192. * Automagically sets up hooks for all methods named "hook_[tag]". Uses the Reflection API.
  193. *
  194. * @return void
  195. */
  196. function set_magic_hooks(){
  197. $class = new ReflectionClass(get_class($this));
  198. $methods = $class->getMethods();
  199. foreach ($methods as $method){
  200. //Check if the method name starts with "hook_"
  201. if (strpos($method->name, 'hook_') === 0){
  202. //Get the hook's tag from the method name
  203. $hook = substr($method->name, 5);
  204. //Add the hook. Uses add_filter because add_action is simply a wrapper of the same.
  205. add_filter($hook, array(&$this, $method->name),
  206. $this->magic_hook_priority, $method->getNumberOfParameters());
  207. }
  208. }
  209. unset($class);
  210. }
  211. /**
  212. * ShadowPluginFramework::activate()
  213. * Stub function for the activation hook. Simply stores the default configuration.
  214. *
  215. * @return void
  216. */
  217. function activate(){
  218. $this->save_options();
  219. }
  220. /**
  221. * ShadowPluginFramework::deactivate()
  222. * Stub function for the deactivation hook. Does nothing.
  223. *
  224. * @return void
  225. */
  226. function deactivate(){
  227. }
  228. /**
  229. * ShadowPluginFramework::plugin_action_links()
  230. * Adds a "Settings" link to the plugin's action links. Default handler for the 'plugin_action_links' hook.
  231. *
  232. * @param array $links
  233. * @param string $file
  234. * @return array
  235. */
  236. function plugin_action_links($links, $file) {
  237. if ($file == $this->plugin_basename)
  238. $links[] = "<a href='" . $this->settings_link . "'>" . __('Settings') . "</a>";
  239. return $links;
  240. }
  241. /**
  242. * ShadowPluginFramework::uninstall()
  243. * Default uninstaller. Removes the plugins configuration record (if available).
  244. *
  245. * @return void
  246. */
  247. function uninstall(){
  248. if ($this->option_name)
  249. delete_option($this->option_name);
  250. }
  251. /**
  252. * Checks if the specified file is inside the mu-plugins directory.
  253. *
  254. * @param string $filename The filename to check. Leave blank to use the current plugin's filename.
  255. * @return bool
  256. */
  257. function is_in_wpmu_plugin_dir( $filename = '' ){
  258. if ( !defined('WPMU_PLUGIN_DIR') ) return false;
  259. if ( empty($filename) ){
  260. $filename = $this->plugin_file;
  261. }
  262. return (strpos( realpath($filename), realpath(WPMU_PLUGIN_DIR) ) !== false);
  263. }
  264. /**
  265. * Check if the plugin is active for the entire network.
  266. * Will return true when the plugin is installed in /mu-plugins/ (WPMU, pre-3.0)
  267. * or has been activated via "Network Activate" (WP 3.0+).
  268. *
  269. * Blame the ridiculous blog/site/network confusion perpetrated by
  270. * the WP API for the silly name.
  271. *
  272. * @return bool
  273. */
  274. function is_super_plugin(){
  275. if ( is_null($this->is_mu_plugin) ){
  276. $this->is_mu_plugin = $this->is_in_wpmu_plugin_dir($this->plugin_file);
  277. }
  278. if ( $this->is_mu_plugin ){
  279. return true;
  280. } else {
  281. return $this->is_plugin_active_for_network($this->plugin_basename);
  282. }
  283. }
  284. /**
  285. * Check whether the plugin is active for the entire network.
  286. *
  287. * Silly WP doesn't load the file that contains this native function until *after*
  288. * all plugins are loaded, so until then we use a copy-pasted version of the same.
  289. *
  290. * @param string $plugin
  291. * @return bool
  292. */
  293. function is_plugin_active_for_network( $plugin ) {
  294. if ( function_exists('is_plugin_active_for_network') ){
  295. return is_plugin_active_for_network($plugin);
  296. }
  297. if ( !is_multisite() )
  298. return false;
  299. $plugins = get_site_option( 'active_sitewide_plugins');
  300. if ( isset($plugins[$plugin]) )
  301. return true;
  302. return false;
  303. }
  304. }
  305. ?>