/app/model/class-ms-model-plugin.php

  1. <?php 
  2. /** 
  3. * M2 Model file. 
  4. * 
  5. * @package Membership2 
  6. * @subpackage Model 
  7. */ 
  8.  
  9. /** 
  10. * Main class for protection. 
  11. * 
  12. * @since 1.0.0 
  13. */ 
  14. class MS_Model_Plugin extends MS_Model { 
  15.  
  16. /** 
  17. * Current Member object. 
  18. * 
  19. * @since 1.0.0 
  20. * 
  21. * @var string $member 
  22. */ 
  23. public $member; 
  24.  
  25. /** 
  26. * Full admin menu, used by the Adminside rule. 
  27. * This property cannot be initialized in the rule-model itself because the 
  28. * rule is loaded long after the menu is rendered and therefore does not 
  29. * have access to the full list of menu items. 
  30. * 
  31. * @since 1.0.0 
  32. * 
  33. * @var array 
  34. */ 
  35. protected $admin_menu = array(); 
  36.  
  37. /** 
  38. * The number of members processed per batch 
  39. * 
  40. * @since 1.0.2.6 
  41. * 
  42. * @var $_process_per_batch 
  43. */ 
  44. private $_process_per_batch = 500; 
  45.  
  46. /** 
  47. * Prepare object. 
  48. * 
  49. * @since 1.0.0 
  50. */ 
  51. public function __construct() { 
  52. do_action( 'ms_model_plugin_constructor', $this ); 
  53.  
  54. /** 
  55. * Define MS_PROCESS_PER_BATCH, set the number of members will be processed per batch 
  56. * 
  57. * Default value is 500 
  58. */ 
  59. if ( defined( 'MS_PROCESS_PER_BATCH' ) && MS_PROCESS_PER_BATCH ) { 
  60. $this->_process_per_batch = intval( MS_PROCESS_PER_BATCH ); 
  61.  
  62. // Upgrade membership database if needs to. 
  63. MS_Model_Upgrade::init(); 
  64.  
  65. /** 
  66. * Create our own copy of the full admin menu to be used in the 
  67. * Membership2 settings. 
  68. * 
  69. * These hooks are only executed in the admin side. 
  70. */ 
  71. $this->add_action( '_network_admin_menu', 'store_admin_menu', 1 ); 
  72. $this->add_action( '_user_admin_menu', 'store_admin_menu', 1 ); 
  73. $this->add_action( '_admin_menu', 'store_admin_menu', 1 ); 
  74.  
  75. $this->add_action( 'network_admin_menu', 'store_admin_menu', 99999 ); 
  76. $this->add_action( 'user_admin_menu', 'store_admin_menu', 99999 ); 
  77. $this->add_action( 'admin_menu', 'store_admin_menu', 99999 ); 
  78.  
  79. // Register all Add-ons and load rules BEFORE the user is initialized. 
  80. $this->add_action( 'ms_load_member', 'load_addons', 1 ); 
  81. $this->add_action( 'ms_load_member', 'load_rules', 1 ); 
  82.  
  83. // Setup the page protection AFTER the user was initialized. 
  84. $this->add_action( 'ms_init_done', 'setup_rules', 1 ); 
  85. $this->add_action( 'ms_init_done', 'setup_protection', 2 ); 
  86. $this->add_action( 'ms_init_done', 'setup_admin_protection', 3 ); 
  87.  
  88. /** 
  89. * Some plugins (such as MarketPress) can trigger the set_current_user 
  90. * action hook before this object is initialized. To ensure correct 
  91. * loading order we use the `init` hook, which is called directly after 
  92. * the correct set_current_user call. 
  93. * 
  94. * Most of the plugin logic requires the current user to be known,  
  95. * that's why we do a explicit check here to make sure we have a valid 
  96. * user. 
  97. */ 
  98.  
  99. // Initialize the current member 
  100. $this->run_action( 'init', 'init_member', 11 ); // Load AFTER the default hook. 
  101.  
  102. /** 
  103. * ******************************************************************* * 
  104. * Hooks below are only set up when Content Protection is enabled 
  105. * ******************************************************************* * 
  106. */ 
  107.  
  108. if ( ! MS_Plugin::is_enabled() ) { return; } 
  109.  
  110. // Setup the CRON hooks. 
  111. $this->run_action( 'init', 'setup_cron_services', 1 ); 
  112. $this->add_filter( 'cron_schedules', 'cron_time_period' ); 
  113. $this->add_filter( 'ms_run_cron_services', 'run_cron_services' ); 
  114. $this->add_action( 'ms_cron_check_membership_status', 'check_membership_status' ); 
  115.  
  116. $this->add_action( 'template_redirect', 'protect_current_page', 1 ); 
  117.  
  118. // Init gateways and communications to register actions/filters. 
  119. $this->run_action( 'init', array( 'MS_Model_Gateway', 'get_gateways' ), 2 ); 
  120. $this->run_action( 'init', array( 'MS_Model_Communication', 'init' ), 2 ); 
  121.  
  122. // Old plugin is enabled? Show a warning! 
  123. if ( class_exists( 'M_Membership' ) ) { 
  124. lib3()->ui->admin_message( 
  125. __( '<b>Warning</b>: The old version of the Membership plugin is active and causes conflicts with the new Membership 2 plugin. Please disable the old Membership plugin.', 'membership2' ),  
  126. 'red' 
  127. ); 
  128.  
  129.  
  130. /** 
  131. * Initialise current member. 
  132. * 
  133. * Get current member and membership relationships. 
  134. * If user is not logged in (visitor), assign a visitor membership. 
  135. * If user is logged in but has not any memberships, assign a default membership. 
  136. * Deactivated users (active == false) get visitor membership assigned. 
  137. * 
  138. * @since 1.0.0 
  139. */ 
  140. public function init_member() { 
  141. do_action( 'ms_load_member', $this ); 
  142.  
  143. $this->member = MS_Model_Member::get_current_member(); 
  144.  
  145. if ( MS_Plugin::is_enabled() ) { 
  146. if ( ! is_user_logged_in() ) { 
  147. // If a Guest-Membership exists we also assign it to the user. 
  148. $ms_guest = MS_Model_Membership::get_guest(); 
  149. if ( $ms_guest->is_valid() && $ms_guest->active ) { 
  150. $this->member->add_membership( $ms_guest->id ); 
  151. } elseif ( ! $this->member->has_membership() ) { 
  152. // Apply User-Membership to logged-in users without subscriptions. 
  153. $ms_user = MS_Model_Membership::get_user(); 
  154. if ( $ms_user->is_valid() && $ms_user->active ) { 
  155. $this->member->add_membership( $ms_user->id ); 
  156. } elseif ( ! $this->member->is_member ) { 
  157. $this->member->subscriptions = array(); 
  158.  
  159. // No subscription: Assign the base membership, which only denies access. 
  160. if ( ! $this->member->has_membership() ) { 
  161. $this->member->add_membership( 
  162. MS_Model_Membership::get_base()->id 
  163. ); 
  164.  
  165. /** 
  166. * At this point the plugin is initialized and we are here: 
  167. * - All Add-Ons are registered 
  168. * - All Rules are registered 
  169. * - Know the current User 
  170. * - All Subscriptions/Memberships of the user are loaded 
  171. * - System memberships are already assigned (guest/base) 
  172. * - Payment gateways are registered 
  173. * - Communication settings are loaded 
  174. * 
  175. * Next we tell everybody that we are ready to get serious! 
  176. * 
  177. * What happens next: 
  178. * 1. All Membership-Rules are initialized/merged 
  179. * 2. Front-End Protection is applied 
  180. * 3. Admin-Side Protection is applied 
  181. */ 
  182.  
  183. do_action( 'ms_init_done', $this ); 
  184.  
  185. /** 
  186. * Returns an array with access-information on the current page/user 
  187. * 
  188. * @since 1.0.0 
  189. * 
  190. * @return array { 
  191. * Access information 
  192. * 
  193. * @type bool $has_access If the current user can view the current page. 
  194. * @type array $memberships List of active membership-IDs the user has 
  195. * registered to. 
  196. * } 
  197. */ 
  198. public function get_access_info() { 
  199. static $Info = null; 
  200.  
  201. if ( null === $Info ) { 
  202. $Info = array( 
  203. 'has_access' => null,  
  204. 'is_admin' => false,  
  205. 'memberships' => array(),  
  206. 'url' => MS_Helper_Utility::get_current_url(),  
  207. ); 
  208.  
  209. // The ID of the main system membership. 
  210. $base_id = MS_Model_Membership::get_base()->id; 
  211.  
  212. $simulation = $this->member->is_simulated_user() || isset( $_GET['explain'] ) && 'access' == $_GET['explain']; 
  213. if ( $simulation ) { $Info['reason'] = array(); } 
  214.  
  215. if ( $this->member->is_normal_admin() ) { 
  216. // Admins have access to ALL memberships. 
  217. $Info['is_admin'] = true; 
  218. $Info['has_access'] = true; 
  219.  
  220. if ( $simulation ) { 
  221. $Info['reason'][] = __( 'Allow: Admin-User always has access', 'membership2' ); 
  222.  
  223. $memberships = MS_Model_Membership::get_memberships(); 
  224. foreach ( $memberships as $membership ) { 
  225. $Info['memberships'][] = $membership->id; 
  226. } else { 
  227. /** 
  228. * A non-admin visitor is only guaranteed access to special 
  229. * Membership2 pages: 
  230. * Registration, Login, etc. 
  231. */ 
  232. $ms_page = MS_Model_Pages::current_page(); 
  233. if ( $ms_page ) { 
  234. $Info['has_access'] = true; 
  235.  
  236. if ( $simulation ) { 
  237. $Info['reason'][] = __( 'Allow: This is a Membership Page', 'membership2' ); 
  238.  
  239. // Build a list of memberships the user belongs to and check permission. 
  240. foreach ( $this->member->subscriptions as $subscription ) { 
  241. // Verify status of the membership. 
  242. // Only active, trial or canceled (until it expires) status memberships. 
  243. if ( ! $this->member->has_membership( $subscription->membership_id ) ) { 
  244. if ( $simulation ) { 
  245. $Info['reason'][] = sprintf( 
  246. __( 'Skipped: Not a member of "%s"', 'membership2' ),  
  247. $subscription->get_membership()->name 
  248. ); 
  249.  
  250. continue; 
  251.  
  252. if ( $base_id !== $subscription->membership_id ) { 
  253. $Info['memberships'][] = $subscription->membership_id; 
  254.  
  255. // If permission is not clear yet then check current membership... 
  256. if ( true !== $Info['has_access'] ) { 
  257. $membership = $subscription->get_membership(); 
  258. $access = $membership->has_access_to_current_page(); 
  259.  
  260. if ( null === $access ) { 
  261. if ( $simulation ) { 
  262. $Info['reason'][] = sprintf( 
  263. __( 'Ignored: Membership "%s"', 'membership2' ),  
  264. $membership->name 
  265. ); 
  266. $Info['reason'][] = $membership->_access_reason; 
  267. continue; 
  268.  
  269. if ( $simulation ) { 
  270. $Info['reason'][] = sprintf( 
  271. __( '%s: Membership "%s"', 'membership2' ),  
  272. $access ? __( 'Allow', 'membership2' ) : __( 'Deny', 'membership2' ),  
  273. $membership->name 
  274. ); 
  275.  
  276. $Info['deciding_membership'] = $membership->id; 
  277. if ( $access ) { 
  278. $Info['deciding_rule'] = $membership->_allow_rule; 
  279. } else { 
  280. $Info['deciding_rule'] = $membership->_deny_rule; 
  281. $Info['reason'][] = $membership->_access_reason; 
  282.  
  283. $Info['has_access'] = $access; 
  284.  
  285. if ( null === $Info['has_access'] ) { 
  286. $Info['has_access'] = true; 
  287.  
  288. if ( $simulation ) { 
  289. $Info['reason'][] = __( 'Allow: Page is not protected', 'membership2' ); 
  290.  
  291. // "membership-id: 0" means: User does not belong to any membership. 
  292. if ( ! count( $Info['memberships'] ) ) { 
  293. $Info['memberships'][] = 0; 
  294.  
  295. $Info = apply_filters( 'ms_model_plugin_get_access_info', $Info ); 
  296.  
  297. if ( $simulation ) { 
  298. $access = lib3()->session->get_clear( 'ms-access' ); 
  299. lib3()->session->add( 'ms-access', $Info ); 
  300. for ( $i = 0; $i < 9; $i += 1 ) { 
  301. if ( isset( $access[ $i ] ) ) { 
  302. lib3()->session->add( 'ms-access', $access[ $i ] ); 
  303.  
  304. if ( WP_DEBUG && isset( $_GET['explain'] ) && 'access' == $_GET['explain'] ) { 
  305. echo '<style>code{background:#EEE;background:rgba(0, 0, 0, 0.1);padding:1px 4px;}</style>'; 
  306. echo '<h3>Note</h3>'; 
  307. echo '<p>To disable the URL param <code>?explain=access</code> you have to set <code>WP_DEBUG</code> to false.</p>'; 
  308. echo '<hr><h3>Recent Access checks</h3>'; 
  309.  
  310. lib3()->debug->stacktrace_off(); 
  311. foreach ( $access as $item ) { 
  312. if ( $item['has_access'] ) { 
  313. $label = __( 'Allow', 'membership2' ); 
  314. } else { 
  315. $label = __( 'Deny', 'membership2' ); 
  316. printf( 
  317. '<a href="%1$s">%1$s</a>: <strong>%2$s</strong>',  
  318. esc_url( $item['url'] ),  
  319. esc_attr( $label ) 
  320. ); 
  321. // Intended debug output, leave it here. 
  322. lib3()->debug->dump( $item ); 
  323. wp_die( '' ); 
  324.  
  325. return $Info; 
  326.  
  327. /** 
  328. * Checks member permissions and protects current page. 
  329. * 
  330. * Related Action Hooks: 
  331. * - template_redirect 
  332. * 
  333. * @since 1.0.0 
  334. */ 
  335. public function protect_current_page() { 
  336. do_action( 'ms_model_plugin_protect_current_page_before', $this ); 
  337.  
  338. if( defined( 'MS_PROTECTED_MESSAGE_REVERSE_RULE' ) && MS_PROTECTED_MESSAGE_REVERSE_RULE ) { 
  339. $allowed_memberships = array(); 
  340. $memberships = MS_Model_Membership::get_membership_ids(); 
  341. foreach( $memberships as $membership_id ) { 
  342. $membership = MS_Factory::load( 'MS_Model_Membership', $membership_id ); 
  343. if( $membership->has_access_to_current_page() ) { 
  344. $allowed_memberships[$membership->priority] = $membership_id; 
  345. ksort( $allowed_memberships ); 
  346. $protected_membership_id = reset( $allowed_memberships ); 
  347.  
  348. // Admin user has access to everything. 
  349. if ( $this->member->is_normal_admin() ) { 
  350. return; 
  351.  
  352. $access = $this->get_access_info(); 
  353.  
  354. if ( ! $access['has_access'] ) { 
  355. MS_Model_Pages::create_missing_pages(); 
  356. $no_access_page_url = MS_Model_Pages::get_page_url( 
  357. MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT,  
  358. false 
  359. ); 
  360. $current_page_url = MS_Helper_Utility::get_current_url(); 
  361.  
  362. // Don't (re-)redirect the protection page. 
  363. if ( ! MS_Model_Pages::is_membership_page( null, MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT ) ) { 
  364. if( defined( 'MS_PROTECTED_MESSAGE_REVERSE_RULE' ) && MS_PROTECTED_MESSAGE_REVERSE_RULE ) { 
  365. $no_access_page_url = esc_url_raw( 
  366. add_query_arg( 
  367. array( 'redirect_to' => urlencode( $current_page_url ), 'membership_id' => $protected_membership_id ),  
  368. $no_access_page_url 
  369. ); 
  370. }else{ 
  371. $no_access_page_url = esc_url_raw( 
  372. add_query_arg( 
  373. array( 'redirect_to' => urlencode( $current_page_url ) ),  
  374. $no_access_page_url 
  375. ); 
  376.  
  377. $no_access_page_url = apply_filters( 
  378. 'ms_model_plugin_protected_content_page',  
  379. $no_access_page_url 
  380. ); 
  381. wp_safe_redirect( $no_access_page_url ); 
  382.  
  383. exit; 
  384.  
  385. do_action( 'ms_model_plugin_protect_current_page_after', $this ); 
  386.  
  387. /** 
  388. * Load all the Add-ons. 
  389. * 
  390. * Related Action Hooks: 
  391. * - ms_load_member 
  392. * 
  393. * @since 1.0.0 
  394. */ 
  395. public function load_addons() { 
  396. do_action( 'ms_load_addons', $this ); 
  397.  
  398. // Initialize all Add-ons. 
  399. MS_Model_Addon::get_addons(); 
  400.  
  401. /** 
  402. * Load all the rules that are used by the plugin. 
  403. * 
  404. * Related Action Hooks: 
  405. * - ms_load_member 
  406. * 
  407. * @since 1.0.0 
  408. */ 
  409. public function load_rules() { 
  410. do_action( 'ms_load_rules', $this ); 
  411.  
  412. $rule_types = MS_Model_Rule::get_rule_types(); 
  413. $base = MS_Model_Membership::get_base(); 
  414.  
  415. foreach ( $rule_types as $rule_type ) { 
  416. $rule = $base->get_rule( $rule_type ); 
  417.  
  418. /** 
  419. * Load all the rules that are used by the plugin. 
  420. * 
  421. * Related Action Hooks: 
  422. * - ms_init_done 
  423. * 
  424. * @since 1.0.0 
  425. * @throws Exception When function is called too early. 
  426. */ 
  427. public function setup_rules() { 
  428. // Make sure we stick to the correct workflow. 
  429. if ( ! did_action( 'ms_init_done' ) ) { 
  430. throw new Exception( 'setup_rules() is called too early.', 1 ); 
  431. return; 
  432.  
  433. do_action( 'ms_initialize_rules', $this ); 
  434.  
  435. $rule_types = MS_Model_Rule::get_rule_types(); 
  436.  
  437. foreach ( $this->member->subscriptions as $subscription ) { 
  438. foreach ( $rule_types as $rule_type ) { 
  439. $rule = $subscription->get_membership()->get_rule( $rule_type ); 
  440.  
  441. /** 
  442. * Setup initial protection for the front-end. 
  443. * 
  444. * Hide menu and pages, protect media donwload and feeds. 
  445. * Protect feeds. 
  446. * 
  447. * Related Action Hooks: 
  448. * - ms_init_done 
  449. * 
  450. * @since 1.0.0 
  451. * @throws Exception When function called too early. 
  452. */ 
  453. public function setup_protection() { 
  454. if ( is_admin() ) { return; } 
  455.  
  456. // Make sure we stick to the correct workflow. 
  457. if ( ! did_action( 'ms_init_done' ) ) { 
  458. throw new Exception( 'setup_protection() is called too early.', 1 ); 
  459. return; 
  460.  
  461. do_action( 'ms_setup_protection', $this ); 
  462.  
  463. // Search permissions through all memberships joined. 
  464. foreach ( $this->member->subscriptions as $subscription ) { 
  465. // Verify status of the membership. 
  466. // Only active, trial or canceled (until it expires) status memberships. 
  467. if ( ! $this->member->has_membership( $subscription->membership_id ) ) { 
  468. continue; 
  469.  
  470. $membership = $subscription->get_membership(); 
  471. $membership->initialize( $subscription ); 
  472.  
  473. // Protection is not applied for Admin users. 
  474. if ( ! $this->member->is_normal_admin() ) { 
  475. $membership->protect_content(); 
  476.  
  477. do_action( 'ms_setup_protection_done', $this ); 
  478.  
  479. /** 
  480. * Setup initial protection for the admin-side. 
  481. * 
  482. * Related Action Hooks: 
  483. * - ms_init_done 
  484. * 
  485. * @since 1.0.0 
  486. * @throws Exception When function is called too early. 
  487. */ 
  488. public function setup_admin_protection() { 
  489. if ( ! is_admin() ) { return; } 
  490.  
  491. // Make sure we stick to the correct workflow. 
  492. if ( ! did_action( 'ms_init_done' ) ) { 
  493. throw new Exception( 'setup_admin_protection() is called too early.', 1 ); 
  494. return; 
  495.  
  496. do_action( 'ms_setup_admin_protection', $this ); 
  497.  
  498. // Search permissions through all memberships joined. 
  499. foreach ( $this->member->subscriptions as $subscription ) { 
  500. // Verify status of the membership. 
  501. // Only active, trial or canceled (until it expires) status memberships. 
  502. if ( ! $this->member->has_membership( $subscription->membership_id ) ) { 
  503. continue; 
  504.  
  505. $membership = $subscription->get_membership(); 
  506. $membership->initialize( $subscription ); 
  507.  
  508. // Protection is not applied for Admin users. 
  509. if ( ! $this->member->is_normal_admin() ) { 
  510. $membership->protect_admin_content(); 
  511.  
  512. do_action( 'ms_setup_admin_protection_done', $this ); 
  513.  
  514. /** 
  515. * Config cron time period. This is actually not displayed anywhere but 
  516. * used only in function setup_cron_services() 
  517. * 
  518. * Related Action Hooks: 
  519. * - cron_schedules 
  520. * 
  521. * @since 1.0.0 
  522. * @param array $periods Default Cron-Job period values; we add new ones. 
  523. * @return array Modified list of Cron-Job periods. 
  524. */ 
  525. public function cron_time_period( $periods ) { 
  526. if ( ! is_array( $periods ) ) { 
  527. $periods = array(); 
  528.  
  529. $periods['6hours'] = array( 
  530. 'interval' => 6 * HOUR_IN_SECONDS,  
  531. 'display' => __( 'Every 6 Hours', 'membership2' ),  
  532. ); 
  533. $periods['30mins'] = array( 
  534. 'interval' => 30 * MINUTE_IN_SECONDS,  
  535. 'display' => __( 'Every 30 Mins', 'membership2' ),  
  536. ); 
  537.  
  538. return apply_filters( 
  539. 'ms_model_plugin_cron_time_period',  
  540. $periods 
  541. ); 
  542.  
  543. /** 
  544. * Runs a single Membership 2 cron service and then re-schedules it. 
  545. * This function is used to manually trigger the cron services. 
  546. * 
  547. * @since 1.0.0 
  548. * @param string $hook Cron-Job to run on next page load. 
  549. */ 
  550. public function run_cron_services( $hook ) { 
  551. wp_clear_scheduled_hook( $hook ); 
  552. $this->setup_cron_services( $hook ); 
  553.  
  554. // Note that we only remove the cron job and add it again. 
  555. // As a result the job is re-scheduled with current timestamp and 
  556. // therefore it will be executed instantly. 
  557.  
  558. /** 
  559. * Setup cron plugin services. 
  560. * 
  561. * Setup cron to call actions. 
  562. * The action-hook is called via the WordPress Cron implementation on a 
  563. * regular basis - this hooks are set up only once. 
  564. * 
  565. * The Cron jobs can be manually executed by opening the admin page 
  566. * "Membership2 > Settings" and adding URL param "&run_cron=1" 
  567. * 
  568. * @since 1.0.0 
  569. * @param string $reschedule Optional. Hook to re-schedule. 
  570. */ 
  571. public function setup_cron_services( $reschedule = null ) { 
  572. do_action( 'ms_model_plugin_setup_cron_services_before', $this ); 
  573.  
  574. $jobs = array( 
  575. 'ms_cron_check_membership_status' => '6hours',  
  576. 'ms_cron_process_communications' => 'hourly',  
  577. ); 
  578.  
  579. foreach ( $jobs as $hook => $interval ) { 
  580. if ( ! wp_next_scheduled( $hook ) || $hook == $reschedule ) { 
  581. wp_schedule_event( time(), $interval, $hook ); 
  582.  
  583. do_action( 'ms_model_plugin_setup_cron_services_after', $this ); 
  584.  
  585. /** 
  586. * Check membership status. 
  587. * 
  588. * Execute actions when time/period condition are met. 
  589. * E.g. change membership status, add communication to queue, create invoices. 
  590. * 
  591. * @since 1.0.0 
  592. */ 
  593. public function check_membership_status() { 
  594. do_action( 'ms_model_plugin_check_membership_status_before', $this ); 
  595.  
  596. if ( $this->member->is_simulated_user() ) { 
  597. return; 
  598.  
  599. /** 
  600. * For performance reasons we only process a small batch at once. 
  601. * Here we find out, which subscriptions should be processed during 
  602. * the current request. 
  603. */ 
  604. $offset = (int) MS_Factory::get_option( 'ms_batch_check_offset_flag' ); 
  605.  
  606. // Find the next X subscriptions from DB. 
  607. $args = apply_filters( 
  608. 'ms_model_plugin_check_membership_status_get_subscription_args',  
  609. array( 
  610. 'status' => 'valid',  
  611. 'orderby' => 'ID',  
  612. 'posts_per_page' => $this->_process_per_batch,  
  613. 'offset' => $offset,  
  614. 'nopaging' => false,  
  615. ); 
  616. $subscriptions = MS_Model_Relationship::get_subscriptions( $args ); 
  617.  
  618. if ( count( $subscriptions ) < $this->_process_per_batch ) { 
  619. // We processed all subscriptions. Clean up. 
  620. MS_Factory::delete_option( 'ms_batch_check_offset_flag' ); 
  621. } else { 
  622. // We did not process all subscriptions. Remember where to continue. 
  623. MS_Factory::update_option( 
  624. 'ms_batch_check_offset_flag',  
  625. $offset + $this->_process_per_batch 
  626. ); 
  627.  
  628. // Re-scheduling the cron job will run it again on next page load. 
  629. $hook = 'ms_cron_check_membership_status'; 
  630. wp_clear_scheduled_hook( $hook ); 
  631. $this->setup_cron_services( $hook ); 
  632.  
  633. $_SESSION['m2_status_check'] = 'inv'; 
  634.  
  635. // Perform the actual status checks! 
  636. foreach ( $subscriptions as $subscription ) { 
  637. $subscription->check_membership_status(); 
  638.  
  639. do_action( 'ms_model_plugin_check_membership_status_after', $this ); 
  640.  
  641. /** 
  642. * Copies the full WordPress Admin menu before any restriction is applied 
  643. * by WordPress or an Plugin. This menu-information is used on the 
  644. * Membership2/Accessible Content settings pages 
  645. * 
  646. * @since 1.0.0 
  647. * @global array $menu 
  648. * @global array $submenu 
  649. */ 
  650. public function store_admin_menu() { 
  651. global $menu, $submenu; 
  652.  
  653. if ( ! isset( $this->admin_menu['main'] ) ) { 
  654. $this->admin_menu = array( 
  655. 'main' => $menu,  
  656. 'sub' => $submenu,  
  657. ); 
  658. } else { 
  659. foreach ( $menu as $pos => $item ) { 
  660. $this->admin_menu['main'][ $pos ] = $item; 
  661. foreach ( $submenu as $parent => $item ) { 
  662. $this->admin_menu['sub'][ $parent ] = $item; 
  663. ksort( $this->admin_menu['main'] ); 
  664.  
  665. /** 
  666. * Returns the previously stored admin menu items. 
  667. * 
  668. * @since 1.0.0 
  669. * 
  670. * @return array 
  671. */ 
  672. public function get_admin_menu() { 
  673. return $this->admin_menu; 
.