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

  1. <?php 
  2. /** 
  3. * Event model. 
  4. * 
  5. * Persisted by parent class MS_Model_CustomPostType. 
  6. * 
  7. * @since 1.0.0 
  8. * 
  9. * @package Membership2 
  10. * @subpackage Model 
  11. */ 
  12. class MS_Model_Event extends MS_Model_CustomPostType { 
  13.  
  14. /** 
  15. * Model custom post type. 
  16. * 
  17. * Both static and class property are used to handle php 5.2 limitations. 
  18. * 
  19. * @since 1.0.0 
  20. * 
  21. * @var string 
  22. */ 
  23. protected static $POST_TYPE = 'ms_event'; 
  24.  
  25.  
  26. /** 
  27. * Event topic constants. 
  28. * 
  29. * @see $topic 
  30. * 
  31. * @since 1.0.0 
  32. * 
  33. * @var string 
  34. */ 
  35. const TOPIC_MEMBERSHIP = 'membership'; 
  36. const TOPIC_PAYMENT = 'payment'; 
  37. const TOPIC_USER = 'user'; 
  38. const TOPIC_WARNING = 'warning'; 
  39.  
  40. /** 
  41. * Event type constants. 
  42. * 
  43. * @since 1.0.0 
  44. * 
  45. * @var string 
  46. */ 
  47. const TYPE_UPDATED_INFO = 'updated_info'; 
  48. const TYPE_MS_SIGNED_UP = 'signed_up'; 
  49. const TYPE_MS_MOVED = 'moved'; 
  50. const TYPE_MS_EXPIRED = 'expired'; 
  51. const TYPE_MS_TRIAL_EXPIRED = 'trial_expired'; 
  52. const TYPE_MS_DROPPED = 'dropped'; 
  53. const TYPE_MS_RENEWED = 'renewed'; 
  54. const TYPE_MS_DEACTIVATED = 'deactivated'; 
  55. const TYPE_MS_CANCELED = 'canceled'; 
  56. const TYPE_MS_REGISTERED = 'registered'; 
  57. const TYPE_MS_RESETPASSWORD = 'resetpassword'; 
  58. const TYPE_MS_BEFORE_FINISHES = 'before_finishes'; 
  59. const TYPE_MS_AFTER_FINISHES = 'after_finishes'; 
  60. const TYPE_MS_BEFORE_TRIAL_FINISHES = 'before_trial_finishes'; 
  61. const TYPE_MS_TRIAL_FINISHED = 'trial_finished'; 
  62. const TYPE_CREDIT_CARD_EXPIRE = 'credit_card_expire'; 
  63. const TYPE_PAID = 'paid'; 
  64. const TYPE_PAYMENT_FAILED = 'payment_failed'; 
  65. const TYPE_PAYMENT_PENDING = 'payment_pending'; 
  66. const TYPE_PAYMENT_DENIED = 'payment_denied'; 
  67. const TYPE_PAYMENT_BEFORE_DUE = 'payment_before_due'; 
  68. const TYPE_PAYMENT_AFTER_DUE = 'payment_after_made'; 
  69.  
  70. /** 
  71. * Event's membership ID. 
  72. * 
  73. * @since 1.0.0 
  74. * 
  75. * @var int 
  76. */ 
  77. protected $membership_id; 
  78.  
  79. /** 
  80. * Event's ms relationship ID. 
  81. * 
  82. * @since 1.0.0 
  83. * 
  84. * @var int 
  85. */ 
  86. protected $ms_relationship_id; 
  87.  
  88. /** 
  89. * Event topic. 
  90. * 
  91. * Events are grouped by topic. 
  92. * 
  93. * @since 1.0.0 
  94. * 
  95. * @var string 
  96. */ 
  97. protected $topic; 
  98.  
  99. /** 
  100. * Event type. 
  101. * 
  102. * @since 1.0.0 
  103. * 
  104. * @var string 
  105. */ 
  106. protected $type; 
  107.  
  108. /** 
  109. * Event date. 
  110. * 
  111. * @since 1.0.0 
  112. * 
  113. * @var string 
  114. */ 
  115. protected $date; 
  116.  
  117. /** 
  118. * Returns the post-type of the current object. 
  119. * 
  120. * @since 1.0.0 
  121. * @return string The post-type name. 
  122. */ 
  123. public static function get_post_type() { 
  124. return parent::_post_type( self::$POST_TYPE ); 
  125.  
  126. /** 
  127. * Get custom register post type args for this model. 
  128. * 
  129. * @since 1.0.0 
  130. */ 
  131. public static function get_register_post_type_args() { 
  132. $args = array( 
  133. 'label' => __( 'Membership2 Events', 'membership2' ),  
  134. 'exclude_from_search' => true 
  135. ); 
  136.  
  137. return apply_filters( 
  138. 'ms_customposttype_register_args',  
  139. $args,  
  140. self::get_post_type() 
  141. ); 
  142.  
  143. /** 
  144. * Get Event types. 
  145. * 
  146. * @since 1.0.0 
  147. * 
  148. * @return array { 
  149. * array{ 
  150. * @type string $topic The topic name. 
  151. * @type string $desc The topic description. 
  152. * } 
  153. * } 
  154. */ 
  155. public static function get_event_types() { 
  156. $types = array( 
  157. /** 
  158. * User topic. 
  159. */ 
  160. self::TYPE_MS_REGISTERED => array( 
  161. 'topic' => self::TOPIC_USER,  
  162. 'desc' => __( 'Has registered.', 'membership2' ),  
  163. ),  
  164. self::TYPE_MS_RESETPASSWORD => array( 
  165. 'topic' => self::TOPIC_USER,  
  166. 'desc' => __( 'Reset password.', 'membership2' ),  
  167. ),  
  168. self::TYPE_UPDATED_INFO => array( 
  169. 'topic' => self::TOPIC_USER,  
  170. 'desc' => __( 'Has updated billing information.', 'membership2' ),  
  171. ),  
  172. self::TYPE_CREDIT_CARD_EXPIRE => array( 
  173. 'topic' => self::TOPIC_USER,  
  174. 'desc' => __( "Member's credit card expire warning date.", 'membership2' ),  
  175. ),  
  176.  
  177. /** 
  178. * Membership topic. 
  179. */ 
  180. self::TYPE_MS_SIGNED_UP => array( 
  181. 'topic' => self::TOPIC_MEMBERSHIP,  
  182. 'desc' => __( 'Has signed up to membership %s.', 'membership2' ),  
  183. ),  
  184. self::TYPE_MS_MOVED => array( 
  185. 'topic' => self::TOPIC_MEMBERSHIP,  
  186. 'desc' => __( 'Has moved to membership %s.', 'membership2' ),  
  187. ),  
  188. self::TYPE_MS_EXPIRED => array( 
  189. 'topic' => self::TOPIC_MEMBERSHIP,  
  190. 'desc' => __( 'Membership %s has expired.', 'membership2' ),  
  191. ),  
  192. self::TYPE_MS_DROPPED => array( 
  193. 'topic' => self::TOPIC_MEMBERSHIP,  
  194. 'desc' => __( 'Membership %s dropped.', 'membership2' ),  
  195. ),  
  196. self::TYPE_MS_RENEWED => array( 
  197. 'topic' => self::TOPIC_MEMBERSHIP,  
  198. 'desc' => __( 'Membership %s renewed', 'membership2' ),  
  199. ),  
  200. self::TYPE_MS_DEACTIVATED => array( 
  201. 'topic' => self::TOPIC_MEMBERSHIP,  
  202. 'desc' => __( 'Membership %s deactivated', 'membership2' ),  
  203. ),  
  204. self::TYPE_MS_CANCELED => array( 
  205. 'topic' => self::TOPIC_MEMBERSHIP,  
  206. 'desc' => __( 'Membership %s cancelled.', 'membership2' ),  
  207. ),  
  208.  
  209. /** 
  210. * Warning topic. 
  211. */ 
  212. self::TYPE_MS_BEFORE_FINISHES => array( 
  213. 'topic' => self::TOPIC_WARNING,  
  214. 'desc' => __( 'Membership %s about to finish warning date.', 'membership2' ),  
  215. ),  
  216.  
  217. self::TYPE_MS_AFTER_FINISHES => array( 
  218. 'topic' => self::TOPIC_WARNING,  
  219. 'desc' => __( 'Membership %s finished warning date.', 'membership2' ),  
  220. ),  
  221. self::TYPE_MS_BEFORE_TRIAL_FINISHES => array( 
  222. 'topic' => self::TOPIC_WARNING,  
  223. 'desc' => __( 'Membership % s trial about to finish warning date.', 'membership2' ),  
  224. ),  
  225.  
  226. /** 
  227. * Payment topic. 
  228. */ 
  229. self::TYPE_PAID => array( 
  230. 'topic' => self::TOPIC_PAYMENT,  
  231. 'desc' => __( 'Invoice #%2$s for membership %1$s - Paid.', 'membership2' ),  
  232. ),  
  233. self::TYPE_PAYMENT_FAILED => array( 
  234. 'topic' => self::TOPIC_PAYMENT,  
  235. 'desc' => __( 'Invoice #%2$s for membership %1$s - Payment Failed.', 'membership2' ),  
  236. ),  
  237. self::TYPE_PAYMENT_PENDING => array( 
  238. 'topic' => self::TOPIC_PAYMENT,  
  239. 'desc' => __( 'Invoice #%2$s for membership %1$s - Payment Pending.', 'membership2' ),  
  240. ),  
  241. self::TYPE_PAYMENT_DENIED => array( 
  242. 'topic' => self::TOPIC_PAYMENT,  
  243. 'desc' => __( 'Invoice #%2$s for membership %1$s - Payment Denied.', 'membership2' ),  
  244. ),  
  245. self::TYPE_PAYMENT_BEFORE_DUE => array( 
  246. 'topic' => self::TOPIC_PAYMENT,  
  247. 'desc' => __( 'Invoice #%2$s before due date for membership %1$s warning.', 'membership2' ),  
  248. ),  
  249. self::TYPE_PAYMENT_AFTER_DUE => array( 
  250. 'topic' => self::TOPIC_PAYMENT,  
  251. 'desc' => __( 'Invoice #%2$s after due date for membership %1$s warning.', 'membership2' ),  
  252. ),  
  253. ); 
  254.  
  255. return apply_filters( 'ms_model_news_get_event_types', $types ); 
  256.  
  257. /** 
  258. * Get last event of specified type. 
  259. * 
  260. * @since 1.0.0 
  261. * 
  262. * @param MS_Model_Event The $event to search. 
  263. * @return null|MS_Model_Event The found event, or null. 
  264. */ 
  265. public static function get_last_event_of_type( $event ) { 
  266. $found = null; 
  267.  
  268. $args['posts_per_page'] = 1; 
  269. $args['meta_query']['type'] = array( 
  270. 'key' => 'type',  
  271. 'value' => $event->type,  
  272. ); 
  273. $args['meta_query']['user_id'] = array( 
  274. 'key' => 'user_id',  
  275. 'value' => $event->user_id,  
  276. ); 
  277.  
  278. if ( ! empty( $event->ms_relationship_id ) ) { 
  279. $args['meta_query']['ms_relationship_id'] = array( 
  280. 'key' => 'ms_relationship_id',  
  281. 'value' => $event->ms_relationship_id,  
  282. ); 
  283.  
  284. $events = self::get_events( apply_filters( 'ms_model_events_get_events_args', $args ) ); 
  285.  
  286. if ( ! empty( $events[0] ) ) { 
  287. $found = $events[0]; 
  288.  
  289. return apply_filters( 'ms_model_event_get_last_event_of_type', $found, $event ); 
  290.  
  291. /** 
  292. * Verify if is a valid event type 
  293. * 
  294. * @since 1.0.0 
  295. * 
  296. * @param string $type The event type to validate. 
  297. * @return boolean True if valid. 
  298. */ 
  299. public static function is_valid_type( $type ) { 
  300. $valid = array_key_exists( $type, self::get_event_types() ); 
  301.  
  302. return apply_filters( 'ms_model_event_is_valid_type', $valid, $type ); 
  303.  
  304. /** 
  305. * Get topic from event. 
  306. * 
  307. * @since 1.0.0 
  308. * 
  309. * @param string $type The event type. 
  310. * @return string the topic description. 
  311. */ 
  312. public static function get_topic( $type ) { 
  313. $topic = null; 
  314. $types = self::get_event_types(); 
  315.  
  316. if ( ! empty( $types[ $type ]['topic'] ) ) { 
  317. $topic = $types[ $type ]['topic']; 
  318.  
  319. return apply_filters( 'ms_model_event_get_topic', $topic, $type ); 
  320.  
  321. /** 
  322. * Get event description. 
  323. * 
  324. * @since 1.0.0 
  325. * 
  326. * @param string $type The event type. 
  327. * @return string the event description. 
  328. */ 
  329. public static function get_description( $type ) { 
  330. $desc = ''; 
  331.  
  332. $types = self::get_event_types(); 
  333. if ( ! empty( $types[ $type ]['desc'] ) ) { 
  334. $desc = $types[ $type ]['desc']; 
  335.  
  336. return apply_filters( 'ms_model_event_get_description', $desc, $type ); 
  337.  
  338. /** 
  339. * Get the total event count. 
  340. * For list table pagination. 
  341. * 
  342. * @since 1.0.0 
  343. * 
  344. * @param array $args The default query event args. 
  345. * @return int The total count. 
  346. */ 
  347. public static function get_event_count( $args = null ) { 
  348. MS_Factory::select_blog(); 
  349. $args = self::get_query_args( $args ); 
  350. $query = new WP_Query( $args ); 
  351. MS_Factory::revert_blog(); 
  352.  
  353. return apply_filters( 
  354. 'ms_model_event_get_event_count',  
  355. $query->found_posts,  
  356. $args 
  357. ); 
  358.  
  359. /** 
  360. * Get events. 
  361. * 
  362. * @since 1.0.0 
  363. * 
  364. * @param $args The query post args 
  365. * @see @link http://codex.wordpress.org/Class_Reference/WP_Query 
  366. * @return MS_Model_Event[] The events found. 
  367. */ 
  368. public static function get_events( $args = null ) { 
  369. MS_Factory::select_blog(); 
  370. $args = self::get_query_args( $args ); 
  371. $query = new WP_Query( $args ); 
  372. $items = $query->posts; 
  373. $events = array(); 
  374. MS_Factory::revert_blog(); 
  375.  
  376. foreach ( $items as $item ) { 
  377. $events[] = MS_Factory::load( 'MS_Model_Event', $item ); 
  378.  
  379. return apply_filters( 'ms_model_event_get_events', $events, $args ); 
  380.  
  381. /** 
  382. * Get WP_Query object arguments. 
  383. * 
  384. * Default search arguments for this custom post_type. 
  385. * 
  386. * @since 1.0.0 
  387. * 
  388. * @param $args The query post args 
  389. * @see @link http://codex.wordpress.org/Class_Reference/WP_Query 
  390. * @return array $args The parsed args. 
  391. */ 
  392. public static function get_query_args( $args ) { 
  393. $defaults = array( 
  394. 'post_type' => self::get_post_type(),  
  395. 'posts_per_page' => 10,  
  396. 'fields' => 'ids',  
  397. 'post_status' => 'any',  
  398. 'order' => 'DESC',  
  399. ); 
  400.  
  401. if ( ! empty( $args['topic'] ) ) { 
  402. $args['meta_query']['topic'] = array( 
  403. 'key' => 'topic',  
  404. 'value' => $args['topic'],  
  405. ); 
  406. unset( $args['topic'] ); 
  407.  
  408. if ( ! empty( $args['membership_id'] ) ) { 
  409. $args['meta_query']['membership_id'] = array( 
  410. 'key' => 'membership_id',  
  411. 'value' => $args['membership_id'],  
  412. ); 
  413. unset( $args['membership_id'] ); 
  414.  
  415. if ( ! empty( $args['relationship_id'] ) ) { 
  416. $args['meta_query']['relationship_id'] = array( 
  417. 'key' => 'ms_relationship_id',  
  418. 'value' => $args['relationship_id'],  
  419. ); 
  420. unset( $args['membership_id'] ); 
  421.  
  422. $args = wp_parse_args( $args, $defaults ); 
  423.  
  424. return apply_filters( 'ms_model_event_get_query_args', $args ); 
  425.  
  426. /** 
  427. * Create and Save event. 
  428. * 
  429. * Default search arguments for this custom post_type. 
  430. * 
  431. * @since 1.0.0 
  432. * 
  433. * @param string $type The event type. 
  434. * @return mixed $data The additional data to create an event. 
  435. */ 
  436. public static function save_event( $type, $data ) { 
  437. $event = null; 
  438.  
  439. if ( self::is_valid_type( $type ) ) { 
  440. $event = MS_Factory::create( 'MS_Model_Event' ); 
  441. $event->type = $type; 
  442. $event->topic = self::get_topic( $type ); 
  443. $description = ''; 
  444.  
  445. switch ( $event->topic ) { 
  446. case self::TOPIC_PAYMENT: 
  447. case self::TOPIC_WARNING: 
  448. case self::TOPIC_MEMBERSHIP: 
  449. $subscription = $data; 
  450. if ( $subscription->id > 0 ) { 
  451. $membership = $subscription->get_membership(); 
  452. $member = MS_Factory::load( 
  453. 'MS_Model_Member',  
  454. $subscription->user_id 
  455. ); 
  456. $event->user_id = $subscription->user_id; 
  457. $event->membership_id = $subscription->membership_id; 
  458. $event->ms_relationship_id = $subscription->id; 
  459. $event->name = sprintf( 
  460. 'user: %s, membership: %s, type: %s',  
  461. $member->name,  
  462. $membership->name,  
  463. $type 
  464. ); 
  465.  
  466. if ( self::TOPIC_PAYMENT == $event->topic ) { 
  467. $invoice = $subscription->get_current_invoice( false ); 
  468. $description = sprintf( 
  469. self::get_description( $type ),  
  470. $membership->name,  
  471. $invoice ? $invoice->id : '-' 
  472. ); 
  473. } else { 
  474. $description = sprintf( 
  475. self::get_description( $type ),  
  476. $membership->name 
  477. ); 
  478. } else { 
  479. // The subscription has no ID. 
  480. // Possibly it was not saved yet... 
  481. break; 
  482.  
  483. case self::TOPIC_USER: 
  484. if ( $data instanceof MS_Model_Member ) { 
  485. $member = $data; 
  486. $event->user_id = $member->id; 
  487. $event->name = sprintf( 
  488. 'user: %s, type: %s',  
  489. $member->name,  
  490. $type 
  491. ); 
  492. } elseif ( $data instanceof MS_Model_Relationship ) { 
  493. $subscription = $data; 
  494. $membership = $subscription->get_membership(); 
  495. $member = MS_Factory::load( 
  496. 'MS_Model_Member',  
  497. $subscription->user_id 
  498. ); 
  499. $event->user_id = $subscription->user_id; 
  500. $event->membership_id = $subscription->membership_id; 
  501. $event->ms_relationship_id = $subscription->id; 
  502. $event->name = sprintf( 
  503. 'user: %s, membership: %s, type: %s',  
  504. $member->name,  
  505. $membership->name,  
  506. $type 
  507. ); 
  508. $description = self::get_description( $type ); 
  509. break; 
  510.  
  511. default: 
  512. MS_Helper_Debug::log( "Event topic not implemented: '$event->topic'" ); 
  513. break; 
  514.  
  515. $event->description = apply_filters( 'ms_model_event_description', $description, $type, $data ); 
  516. $event->date = MS_Helper_Period::current_date(); 
  517. $event = apply_filters( 'ms_model_news_record_user_signup_object', $event ); 
  518.  
  519. if ( ! self::is_duplicate( $event, $data ) ) { 
  520. $event->save(); 
  521.  
  522. // Hook to these actions to handle event notifications. 
  523. // e.g. auto communication. 
  524. do_action( 'ms_model_event', $event, $data ); 
  525. do_action( 'ms_model_event_' . $type, $event, $data ); 
  526. } else { 
  527. $event = null; 
  528.  
  529. return apply_filters( 
  530. 'ms_model_event_save_event',  
  531. $event,  
  532. $type,  
  533. $data 
  534. ); 
  535.  
  536.  
  537. /** 
  538. * Verify if a event was already created in the same day. 
  539. * 
  540. * @since 1.0.0 
  541. * 
  542. * @param MS_Model_Event $event The event to verify. 
  543. * @param mixed $data The additional data. 
  544. */ 
  545. public static function is_duplicate( $event, $data ) { 
  546. $is_duplicate = false; 
  547.  
  548. $check_events = apply_filters( 
  549. 'ms_model_event_is_duplicate_check_events',  
  550. array( 
  551. self::TYPE_MS_BEFORE_TRIAL_FINISHES,  
  552. self::TYPE_MS_BEFORE_FINISHES,  
  553. self::TYPE_MS_AFTER_FINISHES,  
  554. self::TYPE_CREDIT_CARD_EXPIRE,  
  555. self::TYPE_PAYMENT_BEFORE_DUE,  
  556. self::TYPE_PAYMENT_AFTER_DUE,  
  557. ); 
  558.  
  559. if ( in_array( $event->type, $check_events ) 
  560. && $last_event = self::get_last_event_of_type( $event ) 
  561. ) { 
  562. $event_date = date_i18n( MS_Helper_Period::PERIOD_FORMAT, strtotime( $last_event->date ) ); 
  563. if ( $event_date === MS_Helper_Period::current_date() ) { 
  564. $is_duplicate = true; 
  565.  
  566. return apply_filters( 'ms_model_event_is_duplicate', $is_duplicate, $event, $data ); 
.