class.redux-plugin.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <?php
  2. /**
  3. * ReduxFrameworkPlugin main class
  4. *
  5. * @package ReduxFramework\ReduxFrameworkPlugin
  6. * @since 3.0.0
  7. */
  8. // Exit if accessed directly
  9. if ( ! defined( 'ABSPATH' ) ) {
  10. exit;
  11. }
  12. if ( ! class_exists( 'ReduxFrameworkPlugin' ) ) {
  13. /**
  14. * Main ReduxFrameworkPlugin class
  15. *
  16. * @since 3.0.0
  17. */
  18. class ReduxFrameworkPlugin {
  19. /**
  20. * @const string VERSION The plugin version, used for cache-busting and script file references
  21. * @since 3.0.0
  22. */
  23. const VERSION = '3.6.16';
  24. /**
  25. * @access protected
  26. * @var array $options Array of config options, used to check for demo mode
  27. * @since 3.0.0
  28. */
  29. protected $options = array();
  30. /**
  31. * Use this value as the text domain when translating strings from this plugin. It should match
  32. * the Text Domain field set in the plugin header, as well as the directory name of the plugin.
  33. * Additionally, text domains should only contain letters, number and hypens, not underscores
  34. * or spaces.
  35. *
  36. * @access protected
  37. * @var string $plugin_slug The unique ID (slug) of this plugin
  38. * @since 3.0.0
  39. */
  40. protected $plugin_slug = 'redux-framework';
  41. /**
  42. * @access protected
  43. * @var string $plugin_screen_hook_suffix The slug of the plugin screen
  44. * @since 3.0.0
  45. */
  46. protected $plugin_screen_hook_suffix = null;
  47. /**
  48. * @access protected
  49. * @var string $plugin_network_activated Check for plugin network activation
  50. * @since 3.0.0
  51. */
  52. protected $plugin_network_activated = null;
  53. /**
  54. * @access private
  55. * @var \ReduxFrameworkPlugin $instance The one true ReduxFrameworkPlugin
  56. * @since 3.0.0
  57. */
  58. private static $instance;
  59. /**
  60. * Get active instance
  61. *
  62. * @access public
  63. * @since 3.1.3
  64. * @return self::$instance The one true ReduxFrameworkPlugin
  65. */
  66. public static function instance() {
  67. if ( ! self::$instance ) {
  68. self::$instance = new self;
  69. self::$instance->get_redux_options();
  70. self::$instance->includes();
  71. self::$instance->hooks();
  72. }
  73. return self::$instance;
  74. }
  75. // Shim since we changed the function name. Deprecated.
  76. public static function get_instance() {
  77. if ( ! self::$instance ) {
  78. self::$instance = new self;
  79. self::$instance->get_redux_options();
  80. self::$instance->includes();
  81. self::$instance->hooks();
  82. }
  83. return self::$instance;
  84. }
  85. /**
  86. * Get Redux options
  87. *
  88. * @access public
  89. * @since 3.1.3
  90. * @return void
  91. */
  92. public function get_redux_options() {
  93. // Setup defaults
  94. $defaults = array(
  95. 'demo' => false,
  96. );
  97. // If multisite is enabled
  98. if ( is_multisite() ) {
  99. // Get network activated plugins
  100. $plugins = get_site_option( 'active_sitewide_plugins' );
  101. foreach ( $plugins as $file => $plugin ) {
  102. if ( strpos( $file, 'redux-framework.php' ) !== false ) {
  103. $this->plugin_network_activated = true;
  104. $this->options = get_site_option( 'ReduxFrameworkPlugin', $defaults );
  105. }
  106. }
  107. }
  108. // If options aren't set, grab them now!
  109. if ( empty( $this->options ) ) {
  110. $this->options = get_option( 'ReduxFrameworkPlugin', $defaults );
  111. }
  112. }
  113. /**
  114. * Include necessary files
  115. *
  116. * @access public
  117. * @since 3.1.3
  118. * @return void
  119. */
  120. public function includes() {
  121. // Include ReduxCore
  122. if ( file_exists( dirname( __FILE__ ) . '/ReduxCore/framework.php' ) ) {
  123. require_once dirname( __FILE__ ) . '/ReduxCore/framework.php';
  124. }
  125. if ( isset( ReduxFramework::$_as_plugin ) ) {
  126. ReduxFramework::$_as_plugin = true;
  127. }
  128. if ( file_exists( dirname( __FILE__ ) . '/ReduxCore/redux-extensions/config.php' ) ) {
  129. require_once dirname( __FILE__ ) . '/ReduxCore/redux-extensions/config.php';
  130. }
  131. // Include demo config, if demo mode is active
  132. if ( $this->options['demo'] && file_exists( dirname( __FILE__ ) . '/sample/sample-config.php' ) ) {
  133. require_once dirname( __FILE__ ) . '/sample/sample-config.php';
  134. }
  135. }
  136. /**
  137. * Run action and filter hooks
  138. *
  139. * @access private
  140. * @since 3.1.3
  141. * @return void
  142. */
  143. private function hooks() {
  144. add_action( 'wp_loaded', array( $this, 'options_toggle_check' ) );
  145. // Activate plugin when new blog is added
  146. add_action( 'wpmu_new_blog', array( $this, 'activate_new_site' ) );
  147. // Display admin notices
  148. add_action( 'admin_notices', array( $this, 'admin_notices' ) );
  149. // Edit plugin metalinks
  150. add_filter( 'plugin_row_meta', array( $this, 'plugin_metalinks' ), null, 2 );
  151. add_action( 'activated_plugin', array( $this, 'load_first' ) );
  152. do_action( 'redux/plugin/hooks', $this );
  153. }
  154. public function load_first() {
  155. $plugin_dir = Redux_Helpers::cleanFilePath( WP_PLUGIN_DIR ) . '/';
  156. $self_file = Redux_Helpers::cleanFilePath( __FILE__ );
  157. $path = str_replace( $plugin_dir, '', $self_file );
  158. $path = str_replace( 'class.redux-plugin.php', 'redux-framework.php', $path );
  159. if ( $plugins = get_option( 'active_plugins' ) ) {
  160. if ( $key = array_search( $path, $plugins ) ) {
  161. array_splice( $plugins, $key, 1 );
  162. array_unshift( $plugins, $path );
  163. update_option( 'active_plugins', $plugins );
  164. }
  165. }
  166. }
  167. /**
  168. * Fired on plugin activation
  169. *
  170. * @access public
  171. * @since 3.0.0
  172. *
  173. * @param boolean $network_wide True if plugin is network activated, false otherwise
  174. *
  175. * @return void
  176. */
  177. public static function activate( $network_wide ) {
  178. if ( function_exists( 'is_multisite' ) && is_multisite() ) {
  179. if ( $network_wide ) {
  180. // Get all blog IDs
  181. $blog_ids = self::get_blog_ids();
  182. foreach ( $blog_ids as $blog_id ) {
  183. switch_to_blog( $blog_id );
  184. self::single_activate();
  185. }
  186. restore_current_blog();
  187. } else {
  188. self::single_activate();
  189. }
  190. } else {
  191. self::single_activate();
  192. }
  193. delete_site_transient( 'update_plugins' );
  194. }
  195. /**
  196. * Fired when plugin is deactivated
  197. *
  198. * @access public
  199. * @since 3.0.0
  200. *
  201. * @param boolean $network_wide True if plugin is network activated, false otherwise
  202. *
  203. * @return void
  204. */
  205. public static function deactivate( $network_wide ) {
  206. if ( function_exists( 'is_multisite' ) && is_multisite() ) {
  207. if ( $network_wide ) {
  208. // Get all blog IDs
  209. $blog_ids = self::get_blog_ids();
  210. foreach ( $blog_ids as $blog_id ) {
  211. switch_to_blog( $blog_id );
  212. self::single_deactivate();
  213. }
  214. restore_current_blog();
  215. } else {
  216. self::single_deactivate();
  217. }
  218. } else {
  219. self::single_deactivate();
  220. }
  221. delete_option( 'ReduxFrameworkPlugin' );
  222. }
  223. /**
  224. * Fired when a new WPMU site is activated
  225. *
  226. * @access public
  227. * @since 3.0.0
  228. *
  229. * @param int $blog_id The ID of the new blog
  230. *
  231. * @return void
  232. */
  233. public function activate_new_site( $blog_id ) {
  234. if ( 1 !== did_action( 'wpmu_new_blog' ) ) {
  235. return;
  236. }
  237. switch_to_blog( $blog_id );
  238. self::single_activate();
  239. restore_current_blog();
  240. }
  241. /**
  242. * Get all IDs of blogs that are not activated, not spam, and not deleted
  243. *
  244. * @access private
  245. * @since 3.0.0
  246. * @global object $wpdb
  247. * @return array|false Array of IDs or false if none are found
  248. */
  249. private static function get_blog_ids() {
  250. global $wpdb;
  251. // Get an array of IDs
  252. $sql = "SELECT blog_id FROM $wpdb->blogs
  253. WHERE archived = '0' AND spam = '0'
  254. AND deleted = '0'";
  255. return $wpdb->get_col( $sql );
  256. }
  257. /**
  258. * Fired for each WPMS blog on plugin activation
  259. *
  260. * @access private
  261. * @since 3.0.0
  262. * @return void
  263. */
  264. private static function single_activate() {
  265. $notices = array();
  266. $notices = get_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES', array() );
  267. $notices[] = __( 'Redux Framework has an embedded demo.', 'redux-framework' ) . ' <a href="./plugins.php?ReduxFrameworkPlugin=demo">' . __( 'Click here to activate the sample config file.', 'redux-framework' ) . '</a>';
  268. update_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES', $notices );
  269. }
  270. /**
  271. * Display admin notices
  272. *
  273. * @access public
  274. * @since 3.0.0
  275. * @return void
  276. */
  277. public function admin_notices() {
  278. do_action( 'ReduxFrameworkPlugin_admin_notice' );
  279. $notices = get_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES', '' );
  280. if ( !empty( $notices ) ) {
  281. foreach ( $notices as $notice ) {
  282. echo '<div class="updated notice is-dismissible"><p>' . $notice . '</p></div>';
  283. }
  284. delete_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES' );
  285. }
  286. }
  287. /**
  288. * Fired for each blog when the plugin is deactivated
  289. *
  290. * @access private
  291. * @since 3.0.0
  292. * @return void
  293. */
  294. private static function single_deactivate() {
  295. delete_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES' );
  296. }
  297. /**
  298. * Turn on or off
  299. *
  300. * @access public
  301. * @since 3.0.0
  302. * @global string $pagenow The current page being displayed
  303. * @return void
  304. */
  305. public function options_toggle_check() {
  306. global $pagenow;
  307. if ( $pagenow == 'plugins.php' && is_admin() && ! empty( $_GET['ReduxFrameworkPlugin'] ) ) {
  308. $url = './plugins.php';
  309. if ( $_GET['ReduxFrameworkPlugin'] == 'demo' ) {
  310. if ( $this->options['demo'] == false ) {
  311. $this->options['demo'] = true;
  312. } else {
  313. $this->options['demo'] = false;
  314. }
  315. }
  316. if ( is_multisite() && is_network_admin() && $this->plugin_network_activated ) {
  317. update_site_option( 'ReduxFrameworkPlugin', $this->options );
  318. } else {
  319. update_option( 'ReduxFrameworkPlugin', $this->options );
  320. }
  321. wp_redirect( $url );
  322. }
  323. }
  324. /**
  325. * Add settings action link to plugins page
  326. *
  327. * @access public
  328. * @since 3.0.0
  329. * @return void
  330. */
  331. public function add_action_links( $links ) {
  332. // In case we ever want to do this...
  333. return $links;
  334. /**
  335. * return array_merge(
  336. * array( 'redux_plugin_settings' => '<a href="' . admin_url( 'plugins.php?page=' . 'redux_plugin_settings' ) . '">' . __( 'Settings', 'redux-framework' ) . '</a>' ),
  337. * $links
  338. * );
  339. */
  340. }
  341. /**
  342. * Edit plugin metalinks
  343. *
  344. * @access public
  345. * @since 3.0.0
  346. *
  347. * @param array $links The current array of links
  348. * @param string $file A specific plugin row
  349. *
  350. * @return array The modified array of links
  351. */
  352. public function plugin_metalinks( $links, $file ) {
  353. if ( strpos( $file, 'redux-framework.php' ) !== false && is_plugin_active( $file ) ) {
  354. $new_links = array(
  355. '<a href="' . 'http://' . 'docs.reduxframework.com/" target="_blank">' . __( 'Docs', 'redux-framework' ) . '</a>',
  356. '<a href="' . 'https://' . 'github.com/ReduxFramework/redux-framework" target="_blank">' . __( 'Repo', 'redux-framework' ) . '</a>',
  357. '<a href="' . 'http://' . 'build.reduxframework.com/" target="_blank">' . __( 'Builder', 'redux-framework' ) . '</a>',
  358. '<a href="' . admin_url( 'tools.php?page=redux-support' ) . '">' . __( 'Get Support', 'redux-framework' ) . '</a>',
  359. );
  360. if ( ( is_multisite() && $this->plugin_network_activated ) || ! is_network_admin() || ! is_multisite() ) {
  361. if ( $this->options['demo'] ) {
  362. $new_links[3] .= '<br /><span style="display: block; padding-top: 6px;"><a href="./plugins.php?ReduxFrameworkPlugin=demo" style="color: #bc0b0b;">' . __( 'Deactivate Demo Mode', 'redux-framework' ) . '</a></span>';
  363. } else {
  364. $new_links[3] .= '<br /><span style="display: block; padding-top: 6px;"><a href="./plugins.php?ReduxFrameworkPlugin=demo" style="color: #bc0b0b;">' . __( 'Activate Demo Mode', 'redux-framework' ) . '</a></span>';
  365. }
  366. }
  367. $links = array_merge( $links, $new_links );
  368. }
  369. return $links;
  370. }
  371. }
  372. }