/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. ); 
  135.  
  136. return apply_filters( 
  137. 'ms_customposttype_register_args',  
  138. $args,  
  139. self::get_post_type() 
  140. ); 
  141.  
  142. /** 
  143. * Get Event types. 
  144. * 
  145. * @since 1.0.0 
  146. * 
  147. * @return array { 
  148. * array{ 
  149. * @type string $topic The topic name. 
  150. * @type string $desc The topic description. 
  151. * } 
  152. * } 
  153. */ 
  154. public static function get_event_types() { 
  155. $types = array( 
  156. /** 
  157. * User topic. 
  158. */ 
  159. self::TYPE_MS_REGISTERED => array( 
  160. 'topic' => self::TOPIC_USER,  
  161. 'desc' => __( 'Has registered.', 'membership2' ),  
  162. ),  
  163. self::TYPE_MS_RESETPASSWORD => array( 
  164. 'topic' => self::TOPIC_USER,  
  165. 'desc' => __( 'Reset password.', 'membership2' ),  
  166. ),  
  167. self::TYPE_UPDATED_INFO => array( 
  168. 'topic' => self::TOPIC_USER,  
  169. 'desc' => __( 'Has updated billing information.', 'membership2' ),  
  170. ),  
  171. self::TYPE_CREDIT_CARD_EXPIRE => array( 
  172. 'topic' => self::TOPIC_USER,  
  173. 'desc' => __( "Member's credit card expire warning date.", 'membership2' ),  
  174. ),  
  175.  
  176. /** 
  177. * Membership topic. 
  178. */ 
  179. self::TYPE_MS_SIGNED_UP => array( 
  180. 'topic' => self::TOPIC_MEMBERSHIP,  
  181. 'desc' => __( 'Has signed up to membership %s.', 'membership2' ),  
  182. ),  
  183. self::TYPE_MS_MOVED => array( 
  184. 'topic' => self::TOPIC_MEMBERSHIP,  
  185. 'desc' => __( 'Has moved to membership %s.', 'membership2' ),  
  186. ),  
  187. self::TYPE_MS_EXPIRED => array( 
  188. 'topic' => self::TOPIC_MEMBERSHIP,  
  189. 'desc' => __( 'Membership %s has expired.', 'membership2' ),  
  190. ),  
  191. self::TYPE_MS_DROPPED => array( 
  192. 'topic' => self::TOPIC_MEMBERSHIP,  
  193. 'desc' => __( 'Membership %s dropped.', 'membership2' ),  
  194. ),  
  195. self::TYPE_MS_RENEWED => array( 
  196. 'topic' => self::TOPIC_MEMBERSHIP,  
  197. 'desc' => __( 'Membership %s renewed', 'membership2' ),  
  198. ),  
  199. self::TYPE_MS_DEACTIVATED => array( 
  200. 'topic' => self::TOPIC_MEMBERSHIP,  
  201. 'desc' => __( 'Membership %s deactivated', 'membership2' ),  
  202. ),  
  203. self::TYPE_MS_CANCELED => array( 
  204. 'topic' => self::TOPIC_MEMBERSHIP,  
  205. 'desc' => __( 'Membership %s cancelled.', 'membership2' ),  
  206. ),  
  207.  
  208. /** 
  209. * Warning topic. 
  210. */ 
  211. self::TYPE_MS_BEFORE_FINISHES => array( 
  212. 'topic' => self::TOPIC_WARNING,  
  213. 'desc' => __( 'Membership %s about to finish warning date.', 'membership2' ),  
  214. ),  
  215.  
  216. self::TYPE_MS_AFTER_FINISHES => array( 
  217. 'topic' => self::TOPIC_WARNING,  
  218. 'desc' => __( 'Membership %s finished warning date.', 'membership2' ),  
  219. ),  
  220. self::TYPE_MS_BEFORE_TRIAL_FINISHES => array( 
  221. 'topic' => self::TOPIC_WARNING,  
  222. 'desc' => __( 'Membership % s trial about to finish warning date.', 'membership2' ),  
  223. ),  
  224.  
  225. /** 
  226. * Payment topic. 
  227. */ 
  228. self::TYPE_PAID => array( 
  229. 'topic' => self::TOPIC_PAYMENT,  
  230. 'desc' => __( 'Invoice #%2$s for membership %1$s - Paid.', 'membership2' ),  
  231. ),  
  232. self::TYPE_PAYMENT_FAILED => array( 
  233. 'topic' => self::TOPIC_PAYMENT,  
  234. 'desc' => __( 'Invoice #%2$s for membership %1$s - Payment Failed.', 'membership2' ),  
  235. ),  
  236. self::TYPE_PAYMENT_PENDING => array( 
  237. 'topic' => self::TOPIC_PAYMENT,  
  238. 'desc' => __( 'Invoice #%2$s for membership %1$s - Payment Pending.', 'membership2' ),  
  239. ),  
  240. self::TYPE_PAYMENT_DENIED => array( 
  241. 'topic' => self::TOPIC_PAYMENT,  
  242. 'desc' => __( 'Invoice #%2$s for membership %1$s - Payment Denied.', 'membership2' ),  
  243. ),  
  244. self::TYPE_PAYMENT_BEFORE_DUE => array( 
  245. 'topic' => self::TOPIC_PAYMENT,  
  246. 'desc' => __( 'Invoice #%2$s before due date for membership %1$s warning.', 'membership2' ),  
  247. ),  
  248. self::TYPE_PAYMENT_AFTER_DUE => array( 
  249. 'topic' => self::TOPIC_PAYMENT,  
  250. 'desc' => __( 'Invoice #%2$s after due date for membership %1$s warning.', 'membership2' ),  
  251. ),  
  252. ); 
  253.  
  254. return apply_filters( 'ms_model_news_get_event_types', $types ); 
  255.  
  256. /** 
  257. * Get last event of specified type. 
  258. * 
  259. * @since 1.0.0 
  260. * 
  261. * @param MS_Model_Event The $event to search. 
  262. * @return null|MS_Model_Event The found event, or null. 
  263. */ 
  264. public static function get_last_event_of_type( $event ) { 
  265. $found = null; 
  266.  
  267. $args['posts_per_page'] = 1; 
  268. $args['meta_query']['type'] = array( 
  269. 'key' => 'type',  
  270. 'value' => $event->type,  
  271. ); 
  272. $args['meta_query']['user_id'] = array( 
  273. 'key' => 'user_id',  
  274. 'value' => $event->user_id,  
  275. ); 
  276.  
  277. if ( ! empty( $event->ms_relationship_id ) ) { 
  278. $args['meta_query']['ms_relationship_id'] = array( 
  279. 'key' => 'ms_relationship_id',  
  280. 'value' => $event->ms_relationship_id,  
  281. ); 
  282.  
  283. $events = self::get_events( apply_filters( 'ms_model_events_get_events_args', $args ) ); 
  284.  
  285. if ( ! empty( $events[0] ) ) { 
  286. $found = $events[0]; 
  287.  
  288. return apply_filters( 'ms_model_event_get_last_event_of_type', $found, $event ); 
  289.  
  290. /** 
  291. * Verify if is a valid event type 
  292. * 
  293. * @since 1.0.0 
  294. * 
  295. * @param string $type The event type to validate. 
  296. * @return boolean True if valid. 
  297. */ 
  298. public static function is_valid_type( $type ) { 
  299. $valid = array_key_exists( $type, self::get_event_types() ); 
  300.  
  301. return apply_filters( 'ms_model_event_is_valid_type', $valid, $type ); 
  302.  
  303. /** 
  304. * Get topic from event. 
  305. * 
  306. * @since 1.0.0 
  307. * 
  308. * @param string $type The event type. 
  309. * @return string the topic description. 
  310. */ 
  311. public static function get_topic( $type ) { 
  312. $topic = null; 
  313. $types = self::get_event_types(); 
  314.  
  315. if ( ! empty( $types[ $type ]['topic'] ) ) { 
  316. $topic = $types[ $type ]['topic']; 
  317.  
  318. return apply_filters( 'ms_model_event_get_topic', $topic, $type ); 
  319.  
  320. /** 
  321. * Get event description. 
  322. * 
  323. * @since 1.0.0 
  324. * 
  325. * @param string $type The event type. 
  326. * @return string the event description. 
  327. */ 
  328. public static function get_description( $type ) { 
  329. $desc = ''; 
  330.  
  331. $types = self::get_event_types(); 
  332. if ( ! empty( $types[ $type ]['desc'] ) ) { 
  333. $desc = $types[ $type ]['desc']; 
  334.  
  335. return apply_filters( 'ms_model_event_get_description', $desc, $type ); 
  336.  
  337. /** 
  338. * Get the total event count. 
  339. * For list table pagination. 
  340. * 
  341. * @since 1.0.0 
  342. * 
  343. * @param array $args The default query event args. 
  344. * @return int The total count. 
  345. */ 
  346. public static function get_event_count( $args = null ) { 
  347. MS_Factory::select_blog(); 
  348. $args = self::get_query_args( $args ); 
  349. $query = new WP_Query( $args ); 
  350. MS_Factory::revert_blog(); 
  351.  
  352. return apply_filters( 
  353. 'ms_model_event_get_event_count',  
  354. $query->found_posts,  
  355. $args 
  356. ); 
  357.  
  358. /** 
  359. * Get events. 
  360. * 
  361. * @since 1.0.0 
  362. * 
  363. * @param $args The query post args 
  364. * @see @link http://codex.wordpress.org/Class_Reference/WP_Query 
  365. * @return MS_Model_Event[] The events found. 
  366. */ 
  367. public static function get_events( $args = null ) { 
  368. MS_Factory::select_blog(); 
  369. $args = self::get_query_args( $args ); 
  370. $query = new WP_Query( $args ); 
  371. $items = $query->posts; 
  372. $events = array(); 
  373. MS_Factory::revert_blog(); 
  374.  
  375. foreach ( $items as $item ) { 
  376. $events[] = MS_Factory::load( 'MS_Model_Event', $item ); 
  377.  
  378. return apply_filters( 'ms_model_event_get_events', $events, $args ); 
  379.  
  380. /** 
  381. * Get WP_Query object arguments. 
  382. * 
  383. * Default search arguments for this custom post_type. 
  384. * 
  385. * @since 1.0.0 
  386. * 
  387. * @param $args The query post args 
  388. * @see @link http://codex.wordpress.org/Class_Reference/WP_Query 
  389. * @return array $args The parsed args. 
  390. */ 
  391. public static function get_query_args( $args ) { 
  392. $defaults = array( 
  393. 'post_type' => self::get_post_type(),  
  394. 'posts_per_page' => 10,  
  395. 'fields' => 'ids',  
  396. 'post_status' => 'any',  
  397. 'order' => 'DESC',  
  398. ); 
  399.  
  400. if ( ! empty( $args['topic'] ) ) { 
  401. $args['meta_query']['topic'] = array( 
  402. 'key' => 'topic',  
  403. 'value' => $args['topic'],  
  404. ); 
  405. unset( $args['topic'] ); 
  406.  
  407. if ( ! empty( $args['membership_id'] ) ) { 
  408. $args['meta_query']['membership_id'] = array( 
  409. 'key' => 'membership_id',  
  410. 'value' => $args['membership_id'],  
  411. ); 
  412. unset( $args['membership_id'] ); 
  413.  
  414. if ( ! empty( $args['relationship_id'] ) ) { 
  415. $args['meta_query']['relationship_id'] = array( 
  416. 'key' => 'ms_relationship_id',  
  417. 'value' => $args['relationship_id'],  
  418. ); 
  419. unset( $args['membership_id'] ); 
  420.  
  421. $args = wp_parse_args( $args, $defaults ); 
  422.  
  423. return apply_filters( 'ms_model_event_get_query_args', $args ); 
  424.  
  425. /** 
  426. * Create and Save event. 
  427. * 
  428. * Default search arguments for this custom post_type. 
  429. * 
  430. * @since 1.0.0 
  431. * 
  432. * @param string $type The event type. 
  433. * @return mixed $data The additional data to create an event. 
  434. */ 
  435. public static function save_event( $type, $data ) { 
  436. $event = null; 
  437.  
  438. if ( self::is_valid_type( $type ) ) { 
  439. $event = MS_Factory::create( 'MS_Model_Event' ); 
  440. $event->type = $type; 
  441. $event->topic = self::get_topic( $type ); 
  442. $description = ''; 
  443.  
  444. switch ( $event->topic ) { 
  445. case self::TOPIC_PAYMENT: 
  446. case self::TOPIC_WARNING: 
  447. case self::TOPIC_MEMBERSHIP: 
  448. $subscription = $data; 
  449. if ( $subscription->id > 0 ) { 
  450. $membership = $subscription->get_membership(); 
  451. $member = MS_Factory::load( 
  452. 'MS_Model_Member',  
  453. $subscription->user_id 
  454. ); 
  455. $event->user_id = $subscription->user_id; 
  456. $event->membership_id = $subscription->membership_id; 
  457. $event->ms_relationship_id = $subscription->id; 
  458. $event->name = sprintf( 
  459. 'user: %s, membership: %s, type: %s',  
  460. $member->name,  
  461. $membership->name,  
  462. $type 
  463. ); 
  464.  
  465. if ( self::TOPIC_PAYMENT == $event->topic ) { 
  466. $invoice = $subscription->get_current_invoice( false ); 
  467. $description = sprintf( 
  468. self::get_description( $type ),  
  469. $membership->name,  
  470. $invoice ? $invoice->id : '-' 
  471. ); 
  472. } else { 
  473. $description = sprintf( 
  474. self::get_description( $type ),  
  475. $membership->name 
  476. ); 
  477. } else { 
  478. // The subscription has no ID. 
  479. // Possibly it was not saved yet... 
  480. break; 
  481.  
  482. case self::TOPIC_USER: 
  483. if ( $data instanceof MS_Model_Member ) { 
  484. $member = $data; 
  485. $event->user_id = $member->id; 
  486. $event->name = sprintf( 
  487. 'user: %s, type: %s',  
  488. $member->name,  
  489. $type 
  490. ); 
  491. } elseif ( $data instanceof MS_Model_Relationship ) { 
  492. $subscription = $data; 
  493. $membership = $subscription->get_membership(); 
  494. $member = MS_Factory::load( 
  495. 'MS_Model_Member',  
  496. $subscription->user_id 
  497. ); 
  498. $event->user_id = $subscription->user_id; 
  499. $event->membership_id = $subscription->membership_id; 
  500. $event->ms_relationship_id = $subscription->id; 
  501. $event->name = sprintf( 
  502. 'user: %s, membership: %s, type: %s',  
  503. $member->name,  
  504. $membership->name,  
  505. $type 
  506. ); 
  507. $description = self::get_description( $type ); 
  508. break; 
  509.  
  510. default: 
  511. MS_Helper_Debug::log( "Event topic not implemented: '$event->topic'" ); 
  512. break; 
  513.  
  514. $event->description = apply_filters( 'ms_model_event_description', $description, $type, $data ); 
  515. $event->date = MS_Helper_Period::current_date(); 
  516. $event = apply_filters( 'ms_model_news_record_user_signup_object', $event ); 
  517.  
  518. if ( ! self::is_duplicate( $event, $data ) ) { 
  519. $event->save(); 
  520.  
  521. // Hook to these actions to handle event notifications. 
  522. // e.g. auto communication. 
  523. do_action( 'ms_model_event', $event, $data ); 
  524. do_action( 'ms_model_event_' . $type, $event, $data ); 
  525. } else { 
  526. $event = null; 
  527.  
  528. return apply_filters( 
  529. 'ms_model_event_save_event',  
  530. $event,  
  531. $type,  
  532. $data 
  533. ); 
  534.  
  535.  
  536. /** 
  537. * Verify if a event was already created in the same day. 
  538. * 
  539. * @since 1.0.0 
  540. * 
  541. * @param MS_Model_Event $event The event to verify. 
  542. * @param mixed $data The additional data. 
  543. */ 
  544. public static function is_duplicate( $event, $data ) { 
  545. $is_duplicate = false; 
  546.  
  547. $check_events = apply_filters( 
  548. 'ms_model_event_is_duplicate_check_events',  
  549. array( 
  550. self::TYPE_MS_BEFORE_TRIAL_FINISHES,  
  551. self::TYPE_MS_BEFORE_FINISHES,  
  552. self::TYPE_MS_AFTER_FINISHES,  
  553. self::TYPE_CREDIT_CARD_EXPIRE,  
  554. self::TYPE_PAYMENT_BEFORE_DUE,  
  555. self::TYPE_PAYMENT_AFTER_DUE,  
  556. ); 
  557.  
  558. if ( in_array( $event->type, $check_events ) 
  559. && $last_event = self::get_last_event_of_type( $event ) 
  560. ) { 
  561. $event_date = gmdate( MS_Helper_Period::PERIOD_FORMAT, strtotime( $last_event->date ) ); 
  562. if ( $event_date === MS_Helper_Period::current_date() ) { 
  563. $is_duplicate = true; 
  564.  
  565. return apply_filters( 'ms_model_event_is_duplicate', $is_duplicate, $event, $data ); 
.