MS_Plugin

Primary Membership plugin class.

Defined (1)

The class is defined in the following location(s).

/membership.php  
  1. class MS_Plugin { 
  2.  
  3. /** 
  4. * Singletone instance of the plugin. 
  5. * @since 1.0.0 
  6. * @var MS_Plugin 
  7. */ 
  8. private static $instance = null; 
  9.  
  10. /** 
  11. * Modifier values. 
  12. * @since 1.0.0 
  13. * @var array 
  14. */ 
  15. private static $modifiers = array(); 
  16.  
  17. /** 
  18. * The WordPress internal plugin identifier. 
  19. * @since 1.0.0 
  20. * @var string 
  21. */ 
  22. private $id; 
  23.  
  24. /** 
  25. * The plugin name. 
  26. * @since 1.0.0 
  27. * @var string 
  28. */ 
  29. private $name; 
  30.  
  31. /** 
  32. * The plugin version. 
  33. * @since 1.0.0 
  34. * @var string 
  35. */ 
  36. private $version; 
  37.  
  38. /** 
  39. * The plugin file. 
  40. * @since 1.0.0 
  41. * @var string 
  42. */ 
  43. private $file; 
  44.  
  45. /** 
  46. * The plugin path. 
  47. * @since 1.0.0 
  48. * @var string 
  49. */ 
  50. private $dir; 
  51.  
  52. /** 
  53. * The plugin URL. 
  54. * @since 1.0.0 
  55. * @var string 
  56. */ 
  57. private $url; 
  58.  
  59. /** 
  60. * The plugin settings. 
  61. * @since 1.0.0 
  62. * @var MS_Model_Settings 
  63. */ 
  64. private $settings; 
  65.  
  66. /** 
  67. * The plugin add-on settings. 
  68. * @since 1.0.0 
  69. * @var MS_Model_Addon 
  70. */ 
  71. private $addon; 
  72.  
  73. /** 
  74. * The main controller of the plugin. 
  75. * @since 1.0.0 
  76. * @var MS_Controller_Plugin 
  77. */ 
  78. private $controller; 
  79.  
  80. /** 
  81. * The API controller (for convenience) 
  82. * @since 1.0.0 
  83. * @var MS_Controller_Api 
  84. */ 
  85. public static $api = null; 
  86.  
  87. /** 
  88. * Plugin constructor. 
  89. * Set properties, registers hooks and loads the plugin. 
  90. * @since 1.0.0 
  91. */ 
  92. public function __construct() { 
  93.  
  94. /** 
  95. * Actions to execute before the plugin construction starts. 
  96. * @since 1.0.0 
  97. * @param object $this The MS_Plugin object. 
  98. */ 
  99. do_action( 'ms_plugin_init', $this ); 
  100.  
  101. /** 
  102. * @since 1.0.0 
  103. * @deprecated since 2.0.0 
  104. */ 
  105. do_action( 'ms_plugin_construct_start', $this ); 
  106.  
  107. /** Setup plugin properties */ 
  108. $this->id = MS_PLUGIN; 
  109. $this->name = MS_PLUGIN_NAME; 
  110. $this->version = MS_PLUGIN_VERSION; 
  111. $this->file = __FILE__; 
  112. $this->dir = plugin_dir_path( __FILE__ ); 
  113. $this->url = plugin_dir_url( __FILE__ ); 
  114.  
  115. add_filter( 
  116. 'ms_class_path_overrides',  
  117. array( $this, 'ms_class_path_overrides' ) 
  118. ); 
  119.  
  120. // Creates the class autoloader. 
  121. spl_autoload_register( array( $this, 'class_loader' ) ); 
  122.  
  123. // Might refresh the Rewrite-Rules and reloads the page. 
  124. add_action( 
  125. 'wp_loaded',  
  126. array( $this, 'maybe_flush_rewrite_rules' ),  
  127. ); 
  128.  
  129. /** 
  130. * Hooks init to register custom post types. 
  131. */ 
  132. add_action( 
  133. 'init',  
  134. array( $this, 'register_custom_post_types' ),  
  135. ); 
  136.  
  137. /** 
  138. * Hooks init to add rewrite rules and tags (both work in conjunction). 
  139. */ 
  140. add_action( 'init', array( $this, 'add_rewrite_rules' ), 1 ); 
  141. add_action( 'init', array( $this, 'add_rewrite_tags' ), 1 ); 
  142.  
  143. // Plugin activation Hook 
  144. register_activation_hook( 
  145. __FILE__,  
  146. array( $this, 'plugin_activation' ) 
  147. ); 
  148.  
  149. /** 
  150. * Hooks init to create the primary plugin controller. 
  151. * We use the setup_theme hook because plugins_loaded is too early: 
  152. * wp_redirect (used by the update model) is initialized after 
  153. * plugins_loaded but before setup_theme. 
  154. */ 
  155. add_action( 
  156. 'setup_theme',  
  157. array( $this, 'ms_plugin_constructing' ) 
  158. ); 
  159.  
  160. /** 
  161. * Creates and Filters the Settings Model. 
  162. * @since 1.0.0 
  163. * @param object $this The MS_Plugin object. 
  164. */ 
  165. $this->settings = MS_Factory::load( 'MS_Model_Settings' ); 
  166.  
  167. /** 
  168. * Creates and Filters the Addon Model. 
  169. * @since 1.0.0 
  170. * @param object $this The MS_Plugin object. 
  171. */ 
  172. $this->addon = MS_Factory::load( 'MS_Model_Addon' ); 
  173.  
  174. add_filter( 
  175. 'plugin_action_links_' . MS_PLUGIN,  
  176. array( $this, 'plugin_settings_link' ) 
  177. ); 
  178.  
  179. add_filter( 
  180. 'network_admin_plugin_action_links_' . MS_PLUGIN,  
  181. array( $this, 'plugin_settings_link' ) 
  182. ); 
  183.  
  184. // Grab instance of self. 
  185. self::$instance = $this; 
  186.  
  187. /** 
  188. * Actions to execute when the Plugin object has successfully constructed. 
  189. * @since 1.0.0 
  190. * @param object $this The MS_Plugin object. 
  191. */ 
  192. do_action( 'ms_plugin_construct_end', $this ); 
  193.  
  194. /** 
  195. * Hooks 'ms_class_path_overrides'. 
  196. * Overrides plugin class paths to adhere to naming conventions 
  197. * where object names are separated by underscores or for special cases. 
  198. * @since 1.0.0 
  199. * @param array $overrides Array passed in by filter. 
  200. * @return array(class=>path) Classes with new file paths. 
  201. */ 
  202. public function ms_class_path_overrides( $overrides ) { 
  203. $models_base = 'app/model/'; 
  204. $models = array( 
  205. 'MS_Model_Communication_After_Finishes' => 'communication/class-ms-model-communication-after-finishes.php',  
  206. 'MS_Model_Communication_After_Payment_Due' => 'communication/class-ms-model-communication-after-payment-due.php',  
  207. 'MS_Model_Communication_Before_Finishes' => 'communication/class-ms-model-communication-before-finishes.php',  
  208. 'MS_Model_Communication_Before_Payment_Due' => 'communication/class-ms-model-communication-before-payment-due.php',  
  209. 'MS_Model_Communication_Before_Trial_Finishes' => 'communication/class-ms-model-communication-before-trial-finishes.php',  
  210. 'MS_Model_Communication_Credit_Card_Expire' => 'communication/class-ms-model-communication-credit-card-expire.php',  
  211. 'MS_Model_Communication_Failed_Payment' => 'communication/class-ms-model-communication-failed-payment.php',  
  212. 'MS_Model_Communication_Info_Update' => 'communication/class-ms-model-communication-info-update.php',  
  213. 'MS_Model_Communication_Registration_Free' => 'communication/class-ms-model-communication-registration-free.php',  
  214. ); 
  215.  
  216. foreach ( $models as $key => $path ) { 
  217. $overrides[ $key ] = $models_base . $path; 
  218.  
  219. return $overrides; 
  220.  
  221. /** 
  222. * Loads primary plugin controllers. 
  223. * Related Action Hooks: 
  224. * - setup_theme 
  225. * @since 1.0.0 
  226. */ 
  227. public function ms_plugin_constructing() { 
  228. /** 
  229. * Creates and Filters the Plugin Controller. 
  230. * ---> MAIN ENTRY POINT CONTROLLER FOR PLUGIN <--- 
  231. * @uses MS_Controller_Plugin 
  232. * @since 1.0.0 
  233. */ 
  234. $this->controller = MS_Factory::create( 'MS_Controller_Plugin' ); 
  235.  
  236. /** 
  237. * Register plugin custom post types. 
  238. * @since 1.0.0 
  239. */ 
  240. public function register_custom_post_types() { 
  241. do_action( 'ms_plugin_register_custom_post_types_before', $this ); 
  242.  
  243. $cpts = apply_filters( 
  244. 'ms_plugin_register_custom_post_types',  
  245. array( 
  246. MS_Model_Membership::get_post_type() => MS_Model_Membership::get_register_post_type_args(),  
  247. MS_Model_Relationship::get_post_type() => MS_Model_Relationship::get_register_post_type_args(),  
  248. MS_Model_Invoice::get_post_type() => MS_Model_Invoice::get_register_post_type_args(),  
  249. MS_Model_Communication::get_post_type() => MS_Model_Communication::get_register_post_type_args(),  
  250. MS_Model_Event::get_post_type() => MS_Model_Event::get_register_post_type_args(),  
  251. ); 
  252.  
  253. foreach ( $cpts as $cpt => $args ) { 
  254. MS_Helper_Utility::register_post_type( $cpt, $args ); 
  255.  
  256. /** 
  257. * Add rewrite rules. 
  258. * @since 1.0.0 
  259. */ 
  260. public function add_rewrite_rules() { 
  261. $settings = MS_Factory::load( 'MS_Model_Settings' ); 
  262.  
  263. // Gateway return - IPN. 
  264. add_rewrite_rule( 
  265. 'ms-payment-return/(.+)/?',  
  266. 'index.php?paymentgateway=$matches[1]',  
  267. 'top' 
  268. ); 
  269.  
  270. // Alternative payment return URL: Membership 
  271. if ( MS_Model_Import_Membership::did_import() ) { 
  272. add_rewrite_rule( 
  273. 'paymentreturn/(.+)/?',  
  274. 'index.php?paymentgateway=$matches[1]',  
  275. 'top' 
  276. ); 
  277.  
  278. // Media / download 
  279. $mmask = $settings->downloads['masked_url']; 
  280. $mtype = $settings->downloads['protection_type']; 
  281.  
  282. if ( MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_MEDIA ) && $mmask ) { 
  283. if ( MS_Rule_Media_Model::PROTECTION_TYPE_HYBRID == $mtype ) { 
  284. add_rewrite_rule( 
  285. sprintf( '^%1$s/?$', $mmask ),  
  286. 'index.php?protectedfile=0',  
  287. 'top' 
  288. ); 
  289. } else { 
  290. add_rewrite_rule( 
  291. sprintf( '^%1$s/([^/]+)', $mmask ),  
  292. 'index.php?protectedfile=$matches[1]',  
  293. 'top' 
  294. ); 
  295. // End: Media / download 
  296.  
  297. do_action( 'ms_plugin_add_rewrite_rules', $this ); 
  298.  
  299. /** 
  300. * Add rewrite tags. 
  301. * @since 1.0.0 
  302. */ 
  303. public function add_rewrite_tags() { 
  304. // Membership site pages. 
  305. add_rewrite_tag( '%ms_page%', '(.+)' ); 
  306.  
  307. // Gateway return - IPN. 
  308. add_rewrite_tag( '%paymentgateway%', '(.+)' ); 
  309.  
  310. // Media / download 
  311. add_rewrite_tag( '%protectedfile%', '(.+)' ); 
  312.  
  313. do_action( 'ms_plugin_add_rewrite_tags', $this ); 
  314.  
  315. /** 
  316. * Actions executed in plugin activation. 
  317. * @since 1.0.0 
  318. */ 
  319. public function plugin_activation() { 
  320. // Prevent recursion during plugin activation. 
  321. $refresh = lib3()->session->get( 'refresh_url_rules' ); 
  322. if ( $refresh ) { return; } 
  323.  
  324. // Update the Membership2 database entries after activation. 
  325. MS_Model_Upgrade::update( true ); 
  326.  
  327. do_action( 'ms_plugin_activation', $this ); 
  328.  
  329. /** 
  330. * Redirect page and request plugin to flush the WordPress rewrite rules 
  331. * on next request. 
  332. * @since 1.0.0 
  333. * @param string $url The URL to load after flushing the rewrite rules. 
  334. */ 
  335. static public function flush_rewrite_rules( $url = false ) { 
  336. if ( isset( $_GET['ms_flushed'] ) && 'yes' == $_GET['ms_flushed'] ) { 
  337. $refresh = true; 
  338. } else { 
  339. $refresh = lib3()->session->get( 'refresh_url_rules' ); 
  340.  
  341. if ( $refresh ) { return; } 
  342.  
  343. lib3()->session->add( 'refresh_url_rules', true ); 
  344.  
  345. // The URL param is only to avoid cache. 
  346. $url = esc_url_raw( 
  347. add_query_arg( 'ms_ts', time(), $url ) 
  348. ); 
  349. wp_safe_redirect( $url ); 
  350. exit; 
  351.  
  352. /** 
  353. * Flush the WordPress rewrite rules. 
  354. * @since 1.0.0 
  355. */ 
  356. public function maybe_flush_rewrite_rules() { 
  357. $refresh = lib3()->session->get_clear( 'refresh_url_rules' ); 
  358. if ( ! $refresh ) { return; } 
  359.  
  360. // Set up the plugin specific rewrite rules again. 
  361. $this->add_rewrite_rules(); 
  362. $this->add_rewrite_tags(); 
  363.  
  364. do_action( 'ms_plugin_flush_rewrite_rules', $this ); 
  365.  
  366. $url = remove_query_arg( 'ms_ts' ); 
  367. $url = esc_url_raw( add_query_arg( 'ms_flushed', 'yes', $url ) ); 
  368. wp_safe_redirect( $url ); 
  369. exit; 
  370.  
  371. /** 
  372. * Class autoloading callback function. 
  373. * Uses the **MS_** namespace to autoload classes when called. 
  374. * Avoids creating include functions for each file in the MVC structure. 
  375. * **MS_** namespace ONLY will be based on folder structure in /app/ 
  376. * @since 1.0.0 
  377. * @param string $class Uses PHP autoloader function. 
  378. * @return boolean 
  379. */ 
  380. private function class_loader( $class ) { 
  381. static $Path_overrides = null; 
  382.  
  383. /** 
  384. * Actions to execute before the autoloader loads a class. 
  385. * @since 1.0.0 
  386. * @param object $this The MS_Plugin object. 
  387. */ 
  388. do_action( 'ms_plugin_class_loader_pre_processing', $this ); 
  389.  
  390. $basedir = dirname( __FILE__ ); 
  391. $class = trim( $class ); 
  392.  
  393. if ( null === $Path_overrides ) { 
  394. /** 
  395. * Adds and Filters class path overrides. 
  396. * @since 1.0.0 
  397. * @param object $this The MS_Plugin object. 
  398. */ 
  399. $Path_overrides = apply_filters( 'ms_class_path_overrides', array(), $this ); 
  400.  
  401. if ( array_key_exists( $class, $Path_overrides ) ) { 
  402. /** 
  403. * Case 1: The class-path is explicitly defined in $Path_overrides. 
  404. * Simply use the defined path to load the class. 
  405. */ 
  406. $file_path = $basedir . '/' . $Path_overrides[ $class ]; 
  407.  
  408. /** 
  409. * Overrides the filename and path. 
  410. * @since 1.0.0 
  411. * @param object $this The MS_Plugin object. 
  412. */ 
  413. $file_path = apply_filters( 'ms_class_file_override', $file_path, $this ); 
  414.  
  415. if ( is_file( $file_path ) ) { 
  416. include_once $file_path; 
  417.  
  418. return true; 
  419. } elseif ( 'MS_' == substr( $class, 0, 3 ) ) { 
  420. /** 
  421. * Case 2: The class-path is not explicitely defined in $Path_overrides. 
  422. * Use /app/ path and class-name to build the file-name. 
  423. */ 
  424.  
  425. $path_array = explode( '_', $class ); 
  426. array_shift( $path_array ); 
  427. $alt_dir = array_pop( $path_array ); 
  428. $sub_path = implode( '/', $path_array ); 
  429.  
  430. $filename = str_replace( '_', '-', 'class-' . $class . '.php' ); 
  431. $file_path = $basedir . '/app/' . strtolower( $sub_path . '/' . $filename ); 
  432. $file_path_alt = $basedir . '/app/' . strtolower( $sub_path . '/' . $alt_dir . '/' . $filename ); 
  433.  
  434. /** 
  435. * Overrides the filename and path. 
  436. * @since 1.0.0 
  437. * @param object $this The MS_Plugin object. 
  438. */ 
  439. $file_path = apply_filters( 'ms_class_file_override', $file_path, $this ); 
  440. $file_path_alt = apply_filters( 'ms_class_file_override', $file_path_alt, $this ); 
  441.  
  442. if ( is_file( $file_path ) ) { 
  443. include_once $file_path; 
  444. } elseif ( is_file( $file_path_alt ) ) { 
  445. include_once $file_path_alt; 
  446.  
  447. return true; 
  448.  
  449. return false; 
  450.  
  451. /** 
  452. * Add link to settings page in plugins page. 
  453. * @since 1.0.0 
  454. * @param array $links WordPress default array of links. 
  455. * @return array Array of links with settings page links added. 
  456. */ 
  457. public function plugin_settings_link( $links ) { 
  458. if ( ! is_network_admin() ) { 
  459. $text = __( 'Settings', 'membership2' ); 
  460. $url = MS_Controller_Plugin::get_admin_url( 'settings' ); 
  461.  
  462. if ( $this->settings->initial_setup ) { 
  463. $url = MS_Controller_Plugin::get_admin_url(); 
  464.  
  465. /** 
  466. * Filter the plugin settings link. 
  467. * @since 1.0.0 
  468. * @param object $this The MS_Plugin object. 
  469. */ 
  470. $settings_link = apply_filters( 
  471. 'ms_plugin_settings_link',  
  472. sprintf( '<a href="%s">%s</a>', $url, $text ),  
  473. $this 
  474. ); 
  475. array_unshift( $links, $settings_link ); 
  476.  
  477. return $links; 
  478.  
  479. /** 
  480. * Returns singleton instance of the plugin. 
  481. * @since 1.0.0 
  482. * @static 
  483. * @access public 
  484. * @return MS_Plugin 
  485. */ 
  486. public static function instance() { 
  487. if ( ! self::$instance ) { 
  488. self::$instance = new MS_Plugin(); 
  489.  
  490. self::$instance = apply_filters( 
  491. 'ms_plugin_instance',  
  492. self::$instance 
  493. ); 
  494.  
  495. return self::$instance; 
  496.  
  497. /** 
  498. * Returns plugin enabled status. 
  499. * @since 1.0.0 
  500. * @access public 
  501. * @static 
  502. * @return bool The status. 
  503. */ 
  504. public static function is_enabled() { 
  505. return self::instance()->settings->plugin_enabled; 
  506.  
  507. /** 
  508. * Returns plugin wizard status. 
  509. * @since 1.0.0 
  510. * @access public 
  511. * @static 
  512. * @return bool The status. 
  513. */ 
  514. public static function is_wizard() { 
  515. return ! ! self::instance()->settings->initial_setup; 
  516.  
  517. /** 
  518. * Returns the network-wide protection status. 
  519. * This flag can be changed by setting the MS_PROTECT_NETWORK flag to true 
  520. * in wp-config.php 
  521. * @since 1.0.0 
  522. * @return bool False means that only the current site is protected. 
  523. * True means that memberships are shared among all network sites. 
  524. */ 
  525. public static function is_network_wide() { 
  526. // THIS IS A PRO FEATURE: 
  527. // IN THE FREE VERSION THIS FUNCTION MUST ALWAYS RETURN FALSE! 
  528. // ELSE YOUR PROTECTION SETTINGS WILL GET MESSED UP. 
  529. return false; 
  530.  
  531. /** 
  532. * Returns a modifier option. 
  533. * This is similar to a setting but more "advanced" in a way that there is 
  534. * no UI for it. A modifier can be set by the plugin (e.g. during Import 
  535. * the "no_messages" modifier is enabled) or via a const in wp-config.php 
  536. * A modifier is never saved in the database. 
  537. * It can be defined ONLY via MS_Plugin::set_modifier() or via wp-config.php 
  538. * The set_modifier() value will always take precedence over wp-config.php 
  539. * definitions. 
  540. * @since 1.0.0 
  541. * @api 
  542. * @param string $key Name of the modifier. 
  543. * @return mixed The modifier value or null. 
  544. */ 
  545. public static function get_modifier( $key ) { 
  546. $res = null; 
  547.  
  548. if ( isset( self::$modifiers[$key] ) ) { 
  549. $res = self::$modifiers[$key]; 
  550. } elseif ( defined( $key ) ) { 
  551. $res = constant( $key ); 
  552.  
  553. return $res; 
  554.  
  555. /** 
  556. * Changes a modifier option. 
  557. * @see get_modifier() for more details. 
  558. * @since 1.0.0 
  559. * @api 
  560. * @param string $key Name of the modifier. 
  561. * @param mixed $value Value of the modifier. `null` unsets the modifier. 
  562. */ 
  563. public static function set_modifier( $key, $value = null ) { 
  564. if ( null === $value ) { 
  565. unset( self::$modifiers[$key] ); 
  566. } else { 
  567. self::$modifiers[$key] = $value; 
  568.  
  569. /** 
  570. * This funciton initializes the api property for easy access to the plugin 
  571. * API. This function is *only* called by MS_Controller_Api::__construct()! 
  572. * @since 1.0.0 
  573. * @internal 
  574. * @param MS_Controller_Api $controller The initialized API controller. 
  575. */ 
  576. public static function set_api( $controller ) { 
  577. self::$api = $controller; 
  578.  
  579. /** 
  580. * Returns property associated with the plugin. 
  581. * @since 1.0.0 
  582. * @access public 
  583. * @param string $property The name of a property. 
  584. * @return mixed Returns mixed value of a property or NULL if a property doesn't exist. 
  585. */ 
  586. public function __get( $property ) { 
  587. if ( property_exists( $this, $property ) ) { 
  588. return $this->$property;