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

  1. <?php 
  2. /** 
  3. * Model. 
  4. * @package Membership2 
  5. */ 
  6.  
  7. /** 
  8. * Communication model. 
  9. * 
  10. * Persisted by parent class MS_Model_CustomPostType. 
  11. * 
  12. * @since 1.0.0 
  13. * 
  14. * @package Membership2 
  15. * @subpackage Model 
  16. */ 
  17. class MS_Model_Communication extends MS_Model_CustomPostType { 
  18.  
  19. /** 
  20. * Model custom post type. 
  21. * 
  22. * Both static and class property are used to handle php 5.2 limitations. 
  23. * 
  24. * @since 1.0.0 
  25. * @var string $POST_TYPE 
  26. */ 
  27. protected static $POST_TYPE = 'ms_communication'; 
  28.  
  29. /** 
  30. * Holds a list of all Communication posts in the database. 
  31. * 
  32. * @since 1.0.1.0 
  33. * @var array $Communication_IDs 
  34. */ 
  35. protected static $Communication_IDs = array(); 
  36.  
  37. /** 
  38. * Communication types, static reference to loaded child objects. 
  39. * 
  40. * @since 1.0.0 
  41. * @var array $communications 
  42. */ 
  43. protected static $communications = array(); 
  44.  
  45. /** 
  46. * Communication type constants. 
  47. * 
  48. * @since 1.0.0 
  49. * @see $type 
  50. * @var string The communication type 
  51. */ 
  52. const COMM_TYPE_REGISTRATION = 'type_registration'; 
  53. const COMM_TYPE_REGISTRATION_FREE = 'type_registration_free'; 
  54. const COMM_TYPE_SIGNUP = 'type_signup'; 
  55. const COMM_TYPE_RESETPASSWORD = 'type_resetpassword'; 
  56. const COMM_TYPE_RENEWED = 'renewed'; 
  57. const COMM_TYPE_INVOICE = 'type_invoice'; 
  58. const COMM_TYPE_BEFORE_FINISHES = 'type_before_finishes'; 
  59. const COMM_TYPE_FINISHED = 'type_finished'; 
  60. const COMM_TYPE_AFTER_FINISHES = 'type_after_finishes'; 
  61. const COMM_TYPE_CANCELLED = 'type_cancelled'; 
  62. const COMM_TYPE_BEFORE_TRIAL_FINISHES = 'type_before_trial_finishes'; 
  63. const COMM_TYPE_INFO_UPDATE = 'type_info_update'; 
  64. const COMM_TYPE_CREDIT_CARD_EXPIRE = 'type_credit_card_expire'; 
  65. const COMM_TYPE_FAILED_PAYMENT = 'type_failed_payment'; 
  66. const COMM_TYPE_BEFORE_PAYMENT_DUE = 'type_before_payment_due'; 
  67. const COMM_TYPE_AFTER_PAYMENT_DUE = 'type_after_payment_due'; 
  68.  
  69. /** 
  70. * Communication variable constants. 
  71. * 
  72. * These variables are used inside emails and are replaced by variable value. 
  73. * 
  74. * @since 1.0.0 
  75. * @see comm_vars 
  76. * @var string The communication variable name. 
  77. */ 
  78. const COMM_VAR_MS_NAME = '%ms-name%'; 
  79. const COMM_VAR_MS_DESCRIPTION = '%ms-description%'; 
  80. const COMM_VAR_MS_INVOICE = '%ms-invoice%'; 
  81. const COMM_VAR_MS_ACCOUNT_PAGE_URL = '%ms-account-page-url%'; 
  82. const COMM_VAR_MS_REMAINING_DAYS = '%ms-remaining-days%'; 
  83. const COMM_VAR_MS_REMAINING_TRIAL_DAYS = '%ms-remaining-trial-days%'; 
  84. const COMM_VAR_MS_EXPIRY_DATE = '%ms-expiry-date%'; 
  85. const COMM_VAR_USER_DISPLAY_NAME = '%user-display-name%'; 
  86. const COMM_VAR_USER_FIRST_NAME = '%user-first-name%'; 
  87. const COMM_VAR_USER_LAST_NAME = '%user-last-name%'; 
  88. const COMM_VAR_USERNAME = '%username%'; 
  89. const COMM_VAR_PASSWORD = '%password%'; 
  90. const COMM_VAR_RESETURL = '%reset-url%'; 
  91. const COMM_VAR_BLOG_NAME = '%blog-name%'; 
  92. const COMM_VAR_BLOG_URL = '%blog-url%'; 
  93. const COMM_VAR_NET_NAME = '%network-name%'; 
  94. const COMM_VAR_NET_URL = '%network-url%'; 
  95.  
  96. /** 
  97. * Communication type. 
  98. * 
  99. * @since 1.0.0 
  100. * @var string The communication type. 
  101. */ 
  102. protected $type; 
  103.  
  104. /** 
  105. * Email subject. 
  106. * 
  107. * @since 1.0.0 
  108. * @var string The email subject. 
  109. */ 
  110. protected $subject; 
  111.  
  112. /** 
  113. * Email body message. 
  114. * 
  115. * @since 1.0.0 
  116. * @var string The email body message. 
  117. */ 
  118. protected $message; 
  119.  
  120. /** 
  121. * Communication period enabled. 
  122. * 
  123. * When the communication has a period to consider. 
  124. * 
  125. * @since 1.0.0 
  126. * @var bool The period enabled status. 
  127. */ 
  128. protected $period_enabled = false; 
  129.  
  130. /** 
  131. * The communication period settings. 
  132. * 
  133. * @since 1.0.0 
  134. * @var array 
  135. */ 
  136. protected $period = array( 
  137. 'period_unit' => 1,  
  138. 'period_type' => MS_Helper_Period::PERIOD_TYPE_DAYS,  
  139. ); 
  140.  
  141. /** 
  142. * Communication enabled status. 
  143. * 
  144. * @since 1.0.0 
  145. * @var string The communication enabled status. 
  146. */ 
  147. protected $enabled; 
  148.  
  149. /** 
  150. * Communication carbon copy enabled. 
  151. * 
  152. * @since 1.0.0 
  153. * @var string The communication carbon copy enabled status. 
  154. */ 
  155. protected $cc_enabled; 
  156.  
  157. /** 
  158. * Communication copied recipient email. 
  159. * 
  160. * @since 1.0.0 
  161. * @var string The copied recipient email. 
  162. */ 
  163. protected $cc_email; 
  164.  
  165. /** 
  166. * Defines a membership_id if this template overrides a default template. 
  167. * 
  168. * Default setting is 0, which indicates that the object is the default 
  169. * template of the specific type. 
  170. * 
  171. * @since 1.0.1.0 
  172. * @var int 
  173. */ 
  174. protected $membership_id = 0; 
  175.  
  176. /** 
  177. * Defines if a membership specific message should be used (true) or the 
  178. * default communication settings should be used (false). 
  179. * 
  180. * Only relevant when $membership_id is set. 
  181. * 
  182. * @since 1.0.1.0 
  183. * @var bool 
  184. */ 
  185. protected $override = false; 
  186.  
  187. /** 
  188. * Communication variables. 
  189. * 
  190. * @since 1.0.0 
  191. * @var string The communication vars. 
  192. */ 
  193. protected $comm_vars = array(); 
  194.  
  195. /** 
  196. * Communication queue of emails to send. 
  197. * 
  198. * @since 1.0.0 
  199. * @var string The communication queue. 
  200. */ 
  201. protected $queue = array(); 
  202.  
  203. /** 
  204. * Communication sent emails queue. 
  205. * 
  206. * Keep for a limited history of sent emails. 
  207. * 
  208. * @since 1.0.0 
  209. * @var string The communication sent queue. 
  210. */ 
  211. protected $sent_queue = array(); 
  212.  
  213. /** 
  214. * Communication default content type. 
  215. * 
  216. * @since 1.0.0 
  217. * @var string The communication default content type. 
  218. */ 
  219. protected $content_type = 'text/html'; 
  220.  
  221. /** 
  222. * Don't persist this fields. 
  223. * 
  224. * @since 1.0.0 
  225. * @var string[] The fields to ignore when persisting. 
  226. */ 
  227. static public $ignore_fields = array( 
  228. 'message',  
  229. 'name',  
  230. 'comm_vars',  
  231. ); 
  232.  
  233.  
  234. /** 
  235. * 
  236. * 
  237. * -------------------------------------------------------------- COLLECTION 
  238. */ 
  239.  
  240.  
  241. /** 
  242. * Returns the post-type of the current object. 
  243. * 
  244. * @since 1.0.0 
  245. * @return string The post-type name. 
  246. */ 
  247. public static function get_post_type() { 
  248. return parent::_post_type( self::$POST_TYPE ); 
  249.  
  250. /** 
  251. * Get custom register post type args for this model. 
  252. * 
  253. * @since 1.0.0 
  254. */ 
  255. public static function get_register_post_type_args() { 
  256. $args = array( 
  257. 'label' => __( 'Membership2 Email Templates', 'membership2' ),  
  258. ); 
  259.  
  260. return apply_filters( 
  261. 'ms_customposttype_register_args',  
  262. $args,  
  263. self::get_post_type() 
  264. ); 
  265.  
  266. /** 
  267. * Initializes the communications module. 
  268. * 
  269. * @since 1.0.1.0 
  270. */ 
  271. public static function init() { 
  272.  
  273. /** 
  274. * Get communication types. 
  275. * 
  276. * @since 1.0.0 
  277. * 
  278. * @return array The communication types. 
  279. */ 
  280. public static function get_communication_types() { 
  281. static $Types = null; 
  282.  
  283. if ( null === $Types ) { 
  284. if ( MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_AUTO_MSGS_PLUS ) ) { 
  285. $Types = array( 
  286. self::COMM_TYPE_REGISTRATION,  
  287. self::COMM_TYPE_REGISTRATION_FREE,  
  288. self::COMM_TYPE_SIGNUP,  
  289. self::COMM_TYPE_RESETPASSWORD,  
  290. self::COMM_TYPE_RENEWED,  
  291. self::COMM_TYPE_INVOICE,  
  292. self::COMM_TYPE_BEFORE_FINISHES,  
  293. self::COMM_TYPE_FINISHED,  
  294. self::COMM_TYPE_AFTER_FINISHES,  
  295. self::COMM_TYPE_CANCELLED,  
  296. self::COMM_TYPE_BEFORE_TRIAL_FINISHES,  
  297. self::COMM_TYPE_INFO_UPDATE,  
  298. self::COMM_TYPE_CREDIT_CARD_EXPIRE,  
  299. self::COMM_TYPE_FAILED_PAYMENT,  
  300. self::COMM_TYPE_BEFORE_PAYMENT_DUE,  
  301. self::COMM_TYPE_AFTER_PAYMENT_DUE,  
  302. ); 
  303. } else { 
  304. $Types = array( 
  305. self::COMM_TYPE_REGISTRATION,  
  306. self::COMM_TYPE_INVOICE,  
  307. self::COMM_TYPE_FINISHED,  
  308. self::COMM_TYPE_CANCELLED,  
  309. self::COMM_TYPE_INFO_UPDATE,  
  310. self::COMM_TYPE_CREDIT_CARD_EXPIRE,  
  311. self::COMM_TYPE_FAILED_PAYMENT,  
  312. ); 
  313.  
  314. return apply_filters( 
  315. 'ms_model_communication_get_communication_types',  
  316. $Types 
  317. ); 
  318.  
  319. /** 
  320. * Get Communication types and respective classes. 
  321. * 
  322. * @since 1.0.0 
  323. * 
  324. * @return array { 
  325. * Return array of $type => $class_name. 
  326. * 
  327. * @type string $type The communication type. 
  328. * @type string $class_name The class name of the communication type. 
  329. * } 
  330. */ 
  331. public static function get_communication_type_classes() { 
  332. static $type_classes; 
  333.  
  334. if ( empty( $type_classes ) ) { 
  335. $type_classes = array( 
  336. self::COMM_TYPE_REGISTRATION => 'MS_Model_Communication_Registration',  
  337. self::COMM_TYPE_REGISTRATION_FREE => 'MS_Model_Communication_Registration_Free',  
  338. self::COMM_TYPE_SIGNUP => 'MS_Model_Communication_Signup',  
  339. self::COMM_TYPE_RESETPASSWORD => 'MS_Model_Communication_Resetpass',  
  340. self::COMM_TYPE_RENEWED => 'MS_Model_Communication_Renewed',  
  341. self::COMM_TYPE_INVOICE => 'MS_Model_Communication_Invoice',  
  342. self::COMM_TYPE_BEFORE_FINISHES => 'MS_Model_Communication_Before_Finishes',  
  343. self::COMM_TYPE_FINISHED => 'MS_Model_Communication_Finished',  
  344. self::COMM_TYPE_AFTER_FINISHES => 'MS_Model_Communication_After_Finishes',  
  345. self::COMM_TYPE_CANCELLED => 'MS_Model_Communication_Cancelled',  
  346. self::COMM_TYPE_BEFORE_TRIAL_FINISHES => 'MS_Model_Communication_Before_Trial_Finishes',  
  347. self::COMM_TYPE_INFO_UPDATE => 'MS_Model_Communication_Info_Update',  
  348. self::COMM_TYPE_CREDIT_CARD_EXPIRE => 'MS_Model_Communication_Credit_Card_Expire',  
  349. self::COMM_TYPE_FAILED_PAYMENT => 'MS_Model_Communication_Failed_Payment',  
  350. self::COMM_TYPE_BEFORE_PAYMENT_DUE => 'MS_Model_Communication_Before_Payment_Due',  
  351. self::COMM_TYPE_AFTER_PAYMENT_DUE => 'MS_Model_Communication_After_Payment_Due',  
  352. ); 
  353.  
  354. return apply_filters( 
  355. 'ms_model_communication_get_communication_type_classes',  
  356. $type_classes 
  357. ); 
  358.  
  359. /** 
  360. * Get Communication types and respective titles. 
  361. * 
  362. * @since 1.0.0 
  363. * 
  364. * @param mixed $membership Optional. If specified only Comm-Types relevant 
  365. * for that membership are returned. 
  366. * @return array { 
  367. * Return array of $type => $title. 
  368. * 
  369. * @type string $type The communication type. 
  370. * @type string $title The title of the communication type. 
  371. * } 
  372. */ 
  373. public static function get_communication_type_titles( $membership = null ) { 
  374. $type_titles = array( 
  375. self::COMM_TYPE_SIGNUP => __( 'Signup - User account created', 'membership2' ),  
  376. self::COMM_TYPE_RESETPASSWORD => __( 'Signup - Forgot Password', 'membership2' ),  
  377. self::COMM_TYPE_REGISTRATION => __( 'Subscription - Completed with payment', 'membership2' ),  
  378. self::COMM_TYPE_REGISTRATION_FREE => __( 'Subscription - Completed (free membership)', 'membership2' ),  
  379. self::COMM_TYPE_RENEWED => __( 'Subscription - Renewed', 'membership2' ),  
  380. self::COMM_TYPE_BEFORE_FINISHES => __( 'Subscription - Before expires', 'membership2' ),  
  381. self::COMM_TYPE_FINISHED => __( 'Subscription - Expired', 'membership2' ),  
  382. self::COMM_TYPE_AFTER_FINISHES => __( 'Subscription - After expired', 'membership2' ),  
  383. self::COMM_TYPE_CANCELLED => __( 'Subscription - Cancelled', 'membership2' ),  
  384. self::COMM_TYPE_BEFORE_TRIAL_FINISHES => __( 'Subscription - Trial finished', 'membership2' ),  
  385. self::COMM_TYPE_INFO_UPDATE => __( 'Payment - Profile updated', 'membership2' ),  
  386. self::COMM_TYPE_CREDIT_CARD_EXPIRE => __( 'Payment - Credit Card expires', 'membership2' ),  
  387. self::COMM_TYPE_INVOICE => __( 'Payment - Receipt/Invoice', 'membership2' ),  
  388. self::COMM_TYPE_FAILED_PAYMENT => __( 'Payment - Failed', 'membership2' ),  
  389. self::COMM_TYPE_BEFORE_PAYMENT_DUE => __( 'Payment - Before due', 'membership2' ),  
  390. self::COMM_TYPE_AFTER_PAYMENT_DUE => __( 'Payment - After due', 'membership2' ),  
  391. ); 
  392.  
  393. foreach ( $type_titles as $type => $title ) { 
  394. if ( ! self::is_valid_communication_type( $type ) ) { 
  395. unset( $type_titles[ $type ] ); 
  396.  
  397. if ( $membership && is_numeric( $membership ) ) { 
  398. $membership = MS_Factory::load( 'MS_Model_Membership', $membership ); 
  399.  
  400. if ( $membership instanceof MS_Model_Membership ) { 
  401. unset( $type_titles[ self::COMM_TYPE_SIGNUP ] ); 
  402. unset( $type_titles[ self::COMM_TYPE_RESETPASSWORD ] ); 
  403.  
  404. if ( ! $membership->has_trial() ) { 
  405. unset( $type_titles[ self::COMM_TYPE_BEFORE_TRIAL_FINISHES ] ); 
  406.  
  407. if ( $membership->is_free() ) { 
  408. unset( $type_titles[ self::COMM_TYPE_REGISTRATION ] ); 
  409. unset( $type_titles[ self::COMM_TYPE_INFO_UPDATE ] ); 
  410. unset( $type_titles[ self::COMM_TYPE_CREDIT_CARD_EXPIRE ] ); 
  411. unset( $type_titles[ self::COMM_TYPE_INVOICE ] ); 
  412. unset( $type_titles[ self::COMM_TYPE_FAILED_PAYMENT ] ); 
  413. unset( $type_titles[ self::COMM_TYPE_BEFORE_PAYMENT_DUE ] ); 
  414. unset( $type_titles[ self::COMM_TYPE_AFTER_PAYMENT_DUE ] ); 
  415. } else { 
  416. unset( $type_titles[ self::COMM_TYPE_REGISTRATION_FREE ] ); 
  417.  
  418. if ( MS_Model_Membership::PAYMENT_TYPE_PERMANENT == $membership->payment_type ) { 
  419. unset( $type_titles[ self::COMM_TYPE_BEFORE_FINISHES ] ); 
  420. unset( $type_titles[ self::COMM_TYPE_FINISHED ] ); 
  421. unset( $type_titles[ self::COMM_TYPE_AFTER_FINISHES ] ); 
  422.  
  423. return apply_filters( 
  424. 'ms_model_communication_get_communication_type_titles',  
  425. $type_titles 
  426. ); 
  427.  
  428. /** 
  429. * Validate communication type. 
  430. * 
  431. * @since 1.0.0 
  432. * 
  433. * @param string $type The type to validate. 
  434. * @return bool True if is valid. 
  435. */ 
  436. public static function is_valid_communication_type( $type ) { 
  437. $valid = ! empty( $type ) 
  438. && in_array( $type, self::get_communication_types() ); 
  439.  
  440. return apply_filters( 
  441. 'ms_model_communication_is_valid_communication_type',  
  442. $valid,  
  443. $type 
  444. ); 
  445.  
  446. /** 
  447. * Get count of all pending email messages. 
  448. * 
  449. * @since 1.0.1.0 
  450. * @return int 
  451. */ 
  452. static public function get_queue_count() { 
  453. $count = 0; 
  454. $memberships = self::get_communication_ids( null ); 
  455.  
  456. foreach ( $memberships as $ids ) { 
  457. foreach ( $ids as $id ) { 
  458. $comm = MS_Factory::load( 'MS_Model_Communication', $id ); 
  459. $count += count( $comm->queue ); 
  460.  
  461. return apply_filters( 
  462. 'ms_model_communication_get_queue_count',  
  463. $count,  
  464. $ids 
  465. ); 
  466.  
  467. /** 
  468. * Returns a list of communication IDs for the specified membership. 
  469. * 
  470. * Possible values: 
  471. * null .. All communication IDs are returned. 
  472. * 0 .. Global communication IDs are returned (defined in Settings page). 
  473. * <MembershipID> .. Communication IDs of that membership are returned. 
  474. * 
  475. * @since 1.0.1.0 
  476. * @param int $membership Indtifies a membership. 
  477. * @return array List of communication IDs. 
  478. */ 
  479. static protected function get_communication_ids( $membership ) { 
  480. if ( ! isset( self::$Communication_IDs[0] ) ) { 
  481. self::$Communication_IDs = array( 
  482. 0 => array(),  
  483. ); 
  484. $args = array( 
  485. 'post_type' => self::get_post_type(),  
  486. 'post_status' => 'any',  
  487. 'fields' => 'ids',  
  488. 'posts_per_page' => -1,  
  489. ); 
  490.  
  491. MS_Factory::select_blog(); 
  492. $query = new WP_Query( $args ); 
  493. $items = $query->posts; 
  494. MS_Factory::revert_blog(); 
  495.  
  496. foreach ( $items as $id ) { 
  497. $comm = MS_Factory::load( 'MS_Model_Communication', $id ); 
  498. self::$Communication_IDs[ $comm->membership_id ][ $comm->type ] = $id; 
  499.  
  500. if ( $membership instanceof MS_Model_Membership ) { 
  501. $key = $membership->id; 
  502. } else { 
  503. $key = $membership; 
  504.  
  505. if ( null === $key ) { 
  506. $result = self::$Communication_IDs; 
  507. } elseif ( isset( self::$Communication_IDs[ $key ] ) ) { 
  508. $result = self::$Communication_IDs[ $key ]; 
  509. } else { 
  510. $result = array(); 
  511.  
  512. return $result; 
  513.  
  514. /** 
  515. * Retrieve and return all communication types objects. 
  516. * 
  517. * @since 1.0.0 
  518. * 
  519. * @param MS_Model_Membership $membership Optional. If defined then we try 
  520. * to load overridden messages for that membership with fallback to 
  521. * the default messages. 
  522. * @return MS_Model_Communication[] The communication objects array. 
  523. */ 
  524. public static function get_communications( $membership = null ) { 
  525. $ids = self::get_communication_ids( $membership ); 
  526. $result = array(); 
  527.  
  528. if ( null === $membership ) { 
  529. // All comm items are requested. Index is counter. 
  530. foreach ( $ids as $sub_list ) { 
  531. foreach ( $sub_list as $type => $id ) { 
  532. $result[] = MS_Factory::load( 'MS_Model_Communication', $id ); 
  533. } else { 
  534. // A single membership is requested. Index is comm-type. 
  535. foreach ( $ids as $type => $id ) { 
  536. $result[ $type ] = MS_Factory::load( 'MS_Model_Communication', $id ); 
  537.  
  538. $types = self::get_communication_types(); 
  539. foreach ( $types as $type ) { 
  540. if ( ! isset( $result[ $type ] ) ) { 
  541. $result[ $type ] = self::get_communication( $type, $membership ); 
  542.  
  543. return apply_filters( 
  544. 'ms_model_communication_get_communications',  
  545. $result,  
  546. $membership 
  547. ); 
  548.  
  549. /** 
  550. * Get communication type object. 
  551. * 
  552. * Load from DB if exists, create a new one if not. 
  553. * 
  554. * @since 1.0.0 
  555. * 
  556. * @param string $type The type of the communication. 
  557. * @param MS_Model_Membership $membership Optional. If defined then we try 
  558. * to load the overridden template for that membership with fallback 
  559. * to the default template. 
  560. * @param bool $no_fallback Optional. Default value is false. 
  561. * True: Always return a communication for specified membership_id 
  562. * False: Fallback to default message if membership_id does not 
  563. * override the requested message. 
  564. * @return MS_Model_Communication The communication object. 
  565. */ 
  566. public static function get_communication( $type, $membership = null, $no_fallback = false ) { 
  567. $comm = null; 
  568. $key = 'all'; 
  569. $comm_id = 0; 
  570.  
  571. /** 
  572. * If the Membership specific communication is not defined or it 
  573. * is configured to use the default communication then fetch the 
  574. * default communication object! 
  575. */ 
  576. $can_fallback = $membership && ! $no_fallback; 
  577.  
  578. if ( self::is_valid_communication_type( $type ) ) { 
  579. $membership_id = 0; 
  580.  
  581. if ( $membership ) { 
  582. if ( $membership instanceof MS_Model_Membership ) { 
  583. $membership_id = $membership->id; 
  584. } elseif ( is_scalar( $membership ) ) { 
  585. $membership_id = $membership; 
  586. if ( $membership_id ) { 
  587. $key = $membership_id; 
  588.  
  589. if ( empty( self::$Communication_IDs[ $key ] ) ) { 
  590. self::$Communication_IDs[ $key ] = array(); 
  591.  
  592. if ( ! empty( self::$Communication_IDs[ $key ][ $type ] ) ) { 
  593. $comm_id = self::$Communication_IDs[ $key ][ $type ]; 
  594. } else { 
  595. $args = array( 
  596. 'post_type' => self::get_post_type(),  
  597. 'post_status' => 'any',  
  598. 'fields' => 'ids',  
  599. 'posts_per_page' => 1,  
  600. 'post_parent' => $membership_id,  
  601. 'meta_query' => array( 
  602. array( 
  603. 'key' => 'type',  
  604. 'value' => $type,  
  605. 'compare' => '=',  
  606. ),  
  607. ),  
  608. ); 
  609.  
  610. $args = apply_filters( 
  611. 'ms_model_communication_get_communications_args',  
  612. $args 
  613. ); 
  614.  
  615. MS_Factory::select_blog(); 
  616. $query = new WP_Query( $args ); 
  617. $items = $query->posts; 
  618. MS_Factory::revert_blog(); 
  619.  
  620. if ( 1 == count( $items ) ) { 
  621. $comm_id = $items[0]; 
  622.  
  623. $comm_classes = self::get_communication_type_classes(); 
  624. $comm_class = $comm_classes[ $type ]; 
  625. if ( $comm_id ) { 
  626. $comm = MS_Factory::load( $comm_class, $comm_id ); 
  627. } elseif ( ! $can_fallback ) { 
  628. $comm = MS_Factory::create( $comm_class ); 
  629. $comm->reset_to_default(); 
  630. $comm->membership_id = $membership_id; 
  631.  
  632. if ( $comm ) { 
  633. self::$Communication_IDs[ $comm->membership_id ][ $type ] = $comm->id; 
  634.  
  635. // If no template found or defined then fallback to default template. 
  636. $should_fallback = ! $comm || ! $comm->override; 
  637. if ( $can_fallback && $should_fallback ) { 
  638. $comm = self::get_communication( $type, null ); 
  639.  
  640. return apply_filters( 
  641. 'ms_model_communication_get_communication_' . $type,  
  642. $comm,  
  643. $membership,  
  644. $no_fallback 
  645. ); 
  646.  
  647.  
  648. /** 
  649. * 
  650. * 
  651. * ------------------------------------------------------------- SINGLE ITEM 
  652. */ 
  653.  
  654.  
  655. /** 
  656. * Communication constructor. 
  657. * 
  658. * @since 1.0.0 
  659. */ 
  660. public function __construct() { 
  661. $this->comm_vars = array( 
  662. self::COMM_VAR_MS_NAME => __( 'Subscription: Membership Name', 'membership2' ),  
  663. self::COMM_VAR_MS_DESCRIPTION => __( 'Subscription: Membership Description', 'membership2' ),  
  664. self::COMM_VAR_MS_REMAINING_DAYS => __( 'Subscription: Remaining days', 'membership2' ),  
  665. self::COMM_VAR_MS_REMAINING_TRIAL_DAYS => __( 'Subscription: Remaining trial days', 'membership2' ),  
  666. self::COMM_VAR_MS_EXPIRY_DATE => __( 'Subscription: Expiration date', 'membership2' ),  
  667. self::COMM_VAR_MS_INVOICE => __( 'Subscription: Current Invoice', 'membership2' ),  
  668. self::COMM_VAR_USER_DISPLAY_NAME => __( 'User: Display name', 'membership2' ),  
  669. self::COMM_VAR_USER_FIRST_NAME => __( 'User: First name', 'membership2' ),  
  670. self::COMM_VAR_USER_LAST_NAME => __( 'User: Last name', 'membership2' ),  
  671. self::COMM_VAR_USERNAME => __( 'User: Login name', 'membership2' ),  
  672. self::COMM_VAR_PASSWORD => __( 'User: Password', 'membership2' ),  
  673. self::COMM_VAR_RESETURL => __( 'User: Reset Password URL', 'membership2' ),  
  674. self::COMM_VAR_MS_ACCOUNT_PAGE_URL => __( 'Site: User Account URL', 'membership2' ),  
  675. self::COMM_VAR_BLOG_NAME => __( 'Site: Name', 'membership2' ),  
  676. self::COMM_VAR_BLOG_URL => __( 'Site: URL', 'membership2' ),  
  677. ); 
  678.  
  679. $has_membership = true; 
  680. if ( self::COMM_TYPE_SIGNUP == $this->type ) { 
  681. $has_membership = false; 
  682. } else { 
  683. // Password is only available in the Signup email. 
  684. unset( $this->comm_vars[ self::COMM_VAR_PASSWORD ] ); 
  685.  
  686. if ( self::COMM_TYPE_RESETPASSWORD == $this->type ) { 
  687. $has_membership = false; 
  688. } else { 
  689. // Reset-Key is only available in the Forgot Password email. 
  690. unset( $this->comm_vars[ self::COMM_VAR_RESETURL ] ); 
  691.  
  692. if ( ! $has_membership ) { 
  693. // If no membership context is available then remove those variables. 
  694. unset( $this->comm_vars[ self::COMM_VAR_MS_NAME ] ); 
  695. unset( $this->comm_vars[ self::COMM_VAR_MS_DESCRIPTION ] ); 
  696. unset( $this->comm_vars[ self::COMM_VAR_MS_REMAINING_DAYS ] ); 
  697. unset( $this->comm_vars[ self::COMM_VAR_MS_REMAINING_TRIAL_DAYS ] ); 
  698. unset( $this->comm_vars[ self::COMM_VAR_MS_EXPIRY_DATE ] ); 
  699. unset( $this->comm_vars[ self::COMM_VAR_MS_INVOICE ] ); 
  700.  
  701. if ( is_multisite() ) { 
  702. $this->comm_vars[ self::COMM_VAR_NET_NAME ] = __( 'Network: Name', 'membership2' ); 
  703. $this->comm_vars[ self::COMM_VAR_NET_URL ] = __( 'Network: URL', 'membership2' ); 
  704.  
  705. /** 
  706. * Save the current communication item. 
  707. * 
  708. * This function allows us easier debugging of communication issues. 
  709. * 
  710. * @since 1.0.1.1 
  711. */ 
  712. public function save() { 
  713. parent::save(); 
  714.  
  715. /** 
  716. * Customize the data that is written to the DB. 
  717. * 
  718. * @param WP_Post $post The post object. 
  719. * @since 1.0.1.0 
  720. */ 
  721. public function save_post_data( $post ) { 
  722. $post['post_content'] = $this->message; 
  723. $post['post_excerpt'] = $this->message; 
  724. $post['post_parent'] = intval( $this->membership_id ); 
  725. return $post; 
  726.  
  727. /** 
  728. * Hook process communication actions. 
  729. * 
  730. * @param WP_Post $post The post object. 
  731. * @since 1.0.1.0 
  732. */ 
  733. public function load_post_data( $post ) { 
  734. $this->message = $post->post_content; 
  735. $this->membership_id = intval( $post->post_parent ); 
  736.  
  737. /** 
  738. * Communication default communication. 
  739. * 
  740. * To be overridden by children classes creating a new object with the default subject, message, enabled, etc. 
  741. * 
  742. * @since 1.0.0 
  743. */ 
  744. public function reset_to_default() { 
  745. do_action( 
  746. 'ms_model_communication_reset_to_default',  
  747. $this->type,  
  748. $this 
  749. ); 
  750.  
  751. /** 
  752. * Returns the title of the communication object. 
  753. * 
  754. * @since 1.0.1.0 
  755. * @return string 
  756. */ 
  757. public function get_title() { 
  758. $result = ''; 
  759. $titles = self::get_communication_type_titles(); 
  760.  
  761. if ( isset( $titles[ $this->type ] ) ) { 
  762. $result = $titles[ $this->type ]; 
  763.  
  764. return apply_filters( 
  765. 'ms_model_communication_get_title',  
  766. $result 
  767. ); 
  768.  
  769. /** 
  770. * Get communication description. 
  771. * 
  772. * Override it in children classes. 
  773. * 
  774. * @since 1.0.0 
  775. * @return string The description. 
  776. */ 
  777. public function get_description() { 
  778. $description = __( 'Override this description in child class', 'membership2' ); 
  779.  
  780. return apply_filters( 
  781. 'ms_model_communication_get_description',  
  782. $description 
  783. ); 
  784.  
  785. /** 
  786. * Populates the field title/description of the Period before/after field 
  787. * in the admin settings. 
  788. * 
  789. * Override this in child classes to customize the label. 
  790. * 
  791. * @since 1.0.0 
  792. * @param array $field A HTML definition, passed to lib3()->html->element(). 
  793. */ 
  794. public function set_period_name( $field ) { 
  795. $field['title'] = __( 'Period before/after', 'membership2' ); 
  796.  
  797. return $field; 
  798.  
  799. /** 
  800. * Process communication. 
  801. * 
  802. * Send email and manage queue. 
  803. * 
  804. * @uses self::send_message() to send the message. 
  805. * 
  806. * @since 1.0.0 
  807. * @internal Called by MS_Controller_Communication::process_queue() 
  808. */ 
  809. public function process_queue() { 
  810. do_action( 
  811. 'ms_model_communication_process_queue_before',  
  812. $this 
  813. ); 
  814.  
  815. /** 
  816. * Use `define( 'MS_STOP_EMAILS', true );` in wp-config.php to prevent 
  817. * Membership2 from sending *any* emails to users. 
  818. * Also any currently enqueued message is removed from the queue 
  819. * 
  820. * @since 1.0.0 
  821. */ 
  822. if ( MS_Plugin::get_modifier( 'MS_STOP_EMAILS' ) ) { 
  823. $this->queue = array(); 
  824.  
  825. if ( $this->enabled && ! $this->check_object_lock() && count( $this->queue ) ) { 
  826. $this->set_object_lock(); 
  827.  
  828. // Max emails that are sent in one process call. 
  829. $max_emails_qty = apply_filters( 
  830. 'ms_model_communication_process_queue_max_email_qty',  
  831. 50 
  832. ); 
  833. $count = 0; 
  834.  
  835. // Email-processing timeout, in seconds. 
  836. $time_limit = apply_filters( 
  837. 'ms_model_communication_process_queue_time_limit',  
  838. 10 
  839. ); 
  840. $start_time = time(); 
  841.  
  842. foreach ( $this->queue as $subscription_id => $timestamp ) { 
  843. // Remove invalid subscription items from queue. 
  844. if ( ! $subscription_id || ! is_numeric( $subscription_id ) ) { 
  845. unset( $this->queue[ $subscription_id ] ); 
  846. continue; 
  847.  
  848. if ( time() > $start_time + $time_limit 
  849. || ++$count > $max_emails_qty 
  850. ) { 
  851. break; 
  852.  
  853. $subscription = MS_Factory::load( 
  854. 'MS_Model_Relationship',  
  855. $subscription_id 
  856. ); 
  857.  
  858. $this->remove_from_queue( $subscription_id ); 
  859. $was_sent = $this->send_message( $subscription ); 
  860.  
  861. if ( ! $was_sent ) { 
  862. $msg = sprintf( 
  863. '[error: Communication email failed] comm_type=%s, subscription_id=%s, user_id=%s',  
  864. $this->type,  
  865. $subscription->id,  
  866. $subscription->user_id 
  867. ); 
  868. lib3()->debug->log( $msg ); 
  869.  
  870. $this->save(); 
  871. $this->delete_object_lock(); 
  872.  
  873. do_action( 'ms_model_communication_process_queue_after', $this ); 
  874.  
  875. /** 
  876. * Enqueue a message in the "send queue". 
  877. * 
  878. * Action handler hooked up in child classes. 
  879. * 
  880. * @since 1.0.0 
  881. * @api 
  882. * @param MS_Model_Event $event The event object. 
  883. * @param MS_Model_Relationship $subscription The subscription to send message to. 
  884. */ 
  885. public function enqueue_messages( $event, $subscription ) { 
  886. do_action( 'ms_model_communication_enqueue_messages_before', $this ); 
  887.  
  888. if ( $this->enabled ) { 
  889. $this->add_to_queue( $subscription->id ); 
  890. $this->save(); 
  891.  
  892. do_action( 'ms_model_communication_enqueue_messages_after', $this ); 
  893.  
  894. /** 
  895. * Process a communication event. 
  896. * 
  897. * This is used to execute custom code before or instead of simply enqueuing 
  898. * the communication. 
  899. * 
  900. * Common usage: 
  901. * - Instantly send the message via $this->send_message() 
  902. * - Only enqueue message for specific $subscriptions (e.g. free ones) 
  903. * 
  904. * @since 1.0.1.0 
  905. * @param MS_Model_Event $event The event object. 
  906. * @param MS_Model_Relationship $subscription The subscription object. 
  907. */ 
  908. public function process_communication( $event, $subscription ) { 
  909. // Can be overwritten in the child class for custom actions. 
  910.  
  911. /** 
  912. * Add a message in the "send queue". 
  913. * 
  914. * @since 1.0.0 
  915. * @api 
  916. * @param int $subscription_id The membership relationship ID to add to queue. 
  917. */ 
  918. public function add_to_queue( $subscription_id ) { 
  919. do_action( 'ms_model_communication_add_to_queue_before', $this ); 
  920.  
  921. /** 
  922. * Documented in process_queue() 
  923. * 
  924. * @since 1.0.0 
  925. */ 
  926. if ( MS_Plugin::get_modifier( 'MS_STOP_EMAILS' ) ) { 
  927. $subscription = MS_Factory::load( 'MS_Model_Relationship', $subscription_id ); 
  928. $msg = sprintf( 
  929. 'Following Email was not sent: "%s" to user "%s".',  
  930. $this->type,  
  931. $subscription->user_id 
  932. ); 
  933. lib3()->debug->log( $msg ); 
  934.  
  935. return false; 
  936.  
  937. $is_enqueued = array_key_exists( $subscription_id, $this->queue ); 
  938.  
  939. if ( $this->enabled && ! $is_enqueued ) { 
  940. $can_add = true; 
  941.  
  942. /** 
  943. * Check if email enqueuing is limited to prevent duplicate emails. 
  944. * 
  945. * Use setting `define( 'MS_DUPLICATE_EMAIL_HOURS', 24 )` to prevent 
  946. * duplicate emails from being sent for 24 hours. 
  947. * 
  948. * @var int Number of hours 
  949. */ 
  950. $pause_hours = 0; 
  951. if ( defined( 'MS_DUPLICATE_EMAIL_HOURS' ) && is_numeric( MS_DUPLICATE_EMAIL_HOURS ) ) { 
  952. $pause_hours = MS_DUPLICATE_EMAIL_HOURS; 
  953. if ( $pause_hours > 0 ) { 
  954. if ( array_key_exists( $subscription_id, $this->sent_queue ) ) { 
  955. $pause_hours = apply_filters( 
  956. 'ms_model_communication_hours_before_resend',  
  957. $pause_hours 
  958. ); 
  959.  
  960. /** 
  961. * The sent_queue is saved in DB and only contains messages 
  962. * from the current Communications object. So 
  963. * $subscription_id defines the email contents and receiver. 
  964. */ 
  965. $sent_date = $this->sent_queue[ $subscription_id ]; 
  966. $now = MS_Helper_Period::current_time(); 
  967.  
  968. $current_delay = MS_Helper_Period::subtract_dates( 
  969. $now,  
  970. $sent_date,  
  971. HOURS_IN_SECONDS 
  972. ); 
  973.  
  974. $can_add = $current_delay >= $pause_hours; 
  975.  
  976. if ( $can_add ) { 
  977. $this->queue[ $subscription_id ] = MS_Helper_Period::current_time(); 
  978.  
  979. do_action( 'ms_model_communication_add_to_queue_after', $this ); 
  980.  
  981. /** 
  982. * Remove from queue. 
  983. * 
  984. * Delete history of sent messages after max is reached. 
  985. * 
  986. * @since 1.0.0 
  987. * 
  988. * @param int $subscription_id The membership relationship ID to remove from queue. 
  989. */ 
  990. public function remove_from_queue( $subscription_id ) { 
  991. do_action( 'ms_model_communication_remove_from_queue_before', $this ); 
  992.  
  993. $max_history = apply_filters( 
  994. 'ms_model_communication_sent_queue_max_history',  
  995. 200 
  996. ); 
  997.  
  998. // Delete history. 
  999. if ( count( $this->sent_queue ) > $max_history ) { 
  1000. $this->sent_queue = array_slice( 
  1001. $this->sent_queue,  
  1002. -100,  
  1003. $max_history,  
  1004. true 
  1005. ); 
  1006.  
  1007. $this->sent_queue[ $subscription_id ] = MS_Helper_Period::current_time(); 
  1008. unset( $this->queue[ $subscription_id ] ); 
  1009.  
  1010. do_action( 'ms_model_communication_remove_from_queue_after', $this ); 
  1011.  
  1012. /** 
  1013. * Send email message. 
  1014. * 
  1015. * THIS IS THE ONLY PLACE IN THE M2 PLUGIN THAT WILL ACTUALLY SEND OUT AN 
  1016. * EMAIL! One exception: If the custom "Reset Password" template is 
  1017. * disabled then `class-ms-controller-dialog.php` will send a default reset 
  1018. * email using a different wp_mail() call. 
  1019. * 
  1020. * Delete history of sent messages after max is reached. 
  1021. * 
  1022. * @since 1.0.0 
  1023. * 
  1024. * @param mixed $reference A reference to identify the member/subscription. 
  1025. * @return bool True if successfully sent email. 
  1026. */ 
  1027. public function send_message( $reference ) { 
  1028. $user_id = 0; 
  1029. $subscription = null; 
  1030. $member = null; 
  1031. $sent = false; 
  1032.  
  1033. if ( $reference instanceof MS_Model_Relationship ) { 
  1034. $user_id = $reference->user_id; 
  1035. $subscription = $reference; 
  1036. $member = $subscription->get_member(); 
  1037. } elseif ( $reference instanceof MS_Model_Member ) { 
  1038. $user_id = $reference->id; 
  1039. $member = $reference; 
  1040. $subscription = null; 
  1041.  
  1042. /** 
  1043. * Documented in process_queue() 
  1044. * 
  1045. * @since 1.0.1.0 
  1046. */ 
  1047. if ( MS_Plugin::get_modifier( 'MS_STOP_EMAILS' ) ) { 
  1048. $msg = sprintf( 
  1049. 'Following Email was not sent: "%s" to user "%s".',  
  1050. $this->type,  
  1051. $user_id 
  1052. ); 
  1053. lib3()->debug->log( $msg ); 
  1054.  
  1055. return false; 
  1056.  
  1057. // Prevent duplicate messages. 
  1058. if ( $subscription ) { 
  1059. $delay = $subscription->seconds_since_last_email( $this->type ); 
  1060.  
  1061. /** 
  1062. * Allow other plugins to customize the duration for ignoring 
  1063. * duplicate emails. This is supposed to be a value in seconds,  
  1064. * so 60 will prevent duplicate emails for 1 minute. 
  1065. * 
  1066. * @since 1.0.3.0 
  1067. * @param int $duration Duration to skip duplicate emails. Default: 1 day. 
  1068. * @param string $type Type of the email that is about to be sent. 
  1069. * @param MS_Model_Relationship $subscription The subscription. 
  1070. */ 
  1071. $ignore_duration = (int) apply_filters( 
  1072. 'ms_communication_send_email_ignore_duration',  
  1073. DAY_IN_SECONDS,  
  1074. $this->type,  
  1075. $subscription 
  1076. ); 
  1077.  
  1078. if ( $delay < $ignore_duration ) { 
  1079. $msg = sprintf( 
  1080. 'Intentionally skip duplicate email: "%s" to user "%s".',  
  1081. $this->type,  
  1082. $user_id 
  1083. ); 
  1084. lib3()->debug->log( $msg ); 
  1085. return false; 
  1086.  
  1087. do_action( 
  1088. 'ms_model_communication_send_message_before',  
  1089. $member,  
  1090. $subscription,  
  1091. $this 
  1092. ); 
  1093.  
  1094. if ( $this->enabled ) { 
  1095. if ( ! is_email( $member->email ) ) { 
  1096. $msg = sprintf( 
  1097. 'Invalid user email. User_id: %1$s, email: %2$s',  
  1098. $user_id,  
  1099. $member->email 
  1100. ); 
  1101. lib3()->debug->log( $msg ); 
  1102.  
  1103. return false; 
  1104.  
  1105. $comm_vars = $this->get_comm_vars( $subscription, $member ); 
  1106. $headers = array(); 
  1107.  
  1108. // Prepare the message: Replace variables. 
  1109. $message = str_replace( 
  1110. array_keys( $comm_vars ),  
  1111. array_values( $comm_vars ),  
  1112. stripslashes( $this->message ) 
  1113. ); 
  1114.  
  1115. // Prepare the subject: Replace variables and remove HTML tags. 
  1116. $subject = str_replace( 
  1117. array_keys( $comm_vars ),  
  1118. array_values( $comm_vars ),  
  1119. stripslashes( $this->subject ) 
  1120. ); 
  1121. $subject = strip_tags( $subject ); 
  1122.  
  1123. // Set the content-type of the email without using WP hooks. 
  1124. $content_type = $this->get_mail_content_type(); 
  1125. $headers[] = sprintf( 
  1126. 'Content-Type: %s; charset="UTF-8"',  
  1127. $content_type 
  1128. ); 
  1129.  
  1130. // Pre-process the message according to content-type. 
  1131. if ( 'text/html' == $content_type ) { 
  1132. $message = wpautop( $message ); 
  1133. $message = make_clickable( $message ); 
  1134. } else { 
  1135. $message = preg_replace( 
  1136. '/\<a .*?href=["\'](.*?)["\'].*?\>(.*?)\<\/a\>/is',  
  1137. '$2 [$1]',  
  1138. $message 
  1139. ); 
  1140. $message = strip_tags( $message ); 
  1141.  
  1142. // Prepare the FROM sender details. 
  1143. $admin_emails = MS_Model_Member::get_admin_user_emails(); 
  1144. if ( ! empty( $admin_emails[0] ) ) { 
  1145. $headers[] = sprintf( 
  1146. 'From: %s <%s> ',  
  1147. get_option( 'blogname' ),  
  1148. $admin_emails[0] 
  1149. ); 
  1150.  
  1151. // Prepare list of recipients. 
  1152. $recipients = array( $member->email ); 
  1153. $cc_recipients = $this->cc_email; 
  1154. if ( $this->cc_enabled && ! empty( $cc_recipients ) ) { 
  1155. $recipients[] = $cc_recipients; 
  1156.  
  1157. // Final step: Allow customization of all email parts. 
  1158. $recipients = apply_filters( 
  1159. 'ms_model_communication_send_message_recipients',  
  1160. $recipients,  
  1161. $this,  
  1162. $subscription 
  1163. ); 
  1164. $message = apply_filters( 
  1165. 'ms_model_communication_send_message_contents',  
  1166. $message,  
  1167. $this,  
  1168. $subscription,  
  1169. $content_type 
  1170. ); 
  1171. $subject = apply_filters( 
  1172. 'ms_model_communication_send_message_subject',  
  1173. $subject,  
  1174. $this,  
  1175. $subscription 
  1176. ); 
  1177. $headers = apply_filters( 
  1178. 'ms_model_communication_send_message_headers',  
  1179. $headers,  
  1180. $this,  
  1181. $subscription 
  1182. ); 
  1183.  
  1184. /** 
  1185. * Send the mail! 
  1186. * wp_mail will not throw an error, so no error-suppression/handling 
  1187. * is required here. On error the function response is FALSE. 
  1188. */ 
  1189. $sent = wp_mail( $recipients, $subject, $message, $headers ); 
  1190.  
  1191. /** 
  1192. * Broadcast that we just send an email to a member. 
  1193. * 
  1194. * @since 1.0.2.7 
  1195. */ 
  1196. do_action( 
  1197. 'ms_model_communication_after_send_message',  
  1198. $sent,  
  1199. $recipients,  
  1200. $subject,  
  1201. $message,  
  1202. $headers,  
  1203. $this,  
  1204. $subscription 
  1205. ); 
  1206.  
  1207. // Log the outgoing email. 
  1208. $msg = sprintf( 
  1209. 'Sent email [%s] to <%s>: %s',  
  1210. $this->type,  
  1211. implode( '>, <', $recipients ),  
  1212. $sent ? 'OK' : 'ERR' 
  1213. ); 
  1214. lib3()->debug->log( $msg ); 
  1215.  
  1216. do_action( 
  1217. 'ms_model_communication_send_message',  
  1218. $member,  
  1219. $subscription,  
  1220. $this 
  1221. ); 
  1222.  
  1223. return $sent; 
  1224.  
  1225. /** 
  1226. * Replace comm_vars with corresponding values. 
  1227. * 
  1228. * @since 1.0.0 
  1229. * 
  1230. * @param MS_Model_Relationship $subscription The membership relationship to send message to. 
  1231. * @param MS_Model_Member $member The member object to get info from. 
  1232. * @return array { 
  1233. * Returns array of ( $var_name => $var_replace ). 
  1234. * 
  1235. * @type string $var_name The variable name to replace. 
  1236. * @type string $var_replace The variable corresponding replace string. 
  1237. * } 
  1238. */ 
  1239. public function get_comm_vars( $subscription, $member ) { 
  1240. $currency = MS_Plugin::instance()->settings->currency . ' '; 
  1241. $invoice = null; 
  1242. $membership = null; 
  1243.  
  1244. if ( $subscription && $subscription instanceof MS_Model_Relationship ) { 
  1245. // First try to fetch the current invoice. 
  1246. $invoice = $subscription->get_current_invoice( false ); 
  1247. $prev_invoice = $subscription->get_previous_invoice(); 
  1248.  
  1249. // If no current invoice exists then fetch the previous invoice. 
  1250. if ( empty( $invoice ) ) { 
  1251. $invoice = $prev_invoice; 
  1252.  
  1253. $membership = $subscription->get_membership(); 
  1254.  
  1255. $comm_vars = apply_filters( 
  1256. 'ms_model_communication_comm_vars',  
  1257. $this->comm_vars,  
  1258. $this->type,  
  1259. $member,  
  1260. $subscription 
  1261. ); 
  1262.  
  1263. $wp_user = $member->get_user(); 
  1264.  
  1265. foreach ( $comm_vars as $key => $description ) { 
  1266. $var_value = ''; 
  1267.  
  1268. switch ( $key ) { 
  1269. case self::COMM_VAR_BLOG_NAME: 
  1270. $var_value = get_option( 'blogname' ); 
  1271. break; 
  1272.  
  1273. case self::COMM_VAR_BLOG_URL: 
  1274. $var_value = get_option( 'home' ); 
  1275. break; 
  1276.  
  1277. case self::COMM_VAR_USERNAME: 
  1278. $var_value = $member->username; 
  1279. break; 
  1280.  
  1281. case self::COMM_VAR_PASSWORD: 
  1282. /** 
  1283. * $member->password is ONLY available in the same request 
  1284. * when the new user account was created! After this we only 
  1285. * have the encrypted password in the DB, and the plain-text 
  1286. * version will never be available again in code... 
  1287. * 
  1288. * @since 1.0.1.1 
  1289. */ 
  1290. if ( self::COMM_TYPE_SIGNUP == $this->type ) { 
  1291. $var_value = $member->password; 
  1292. break; 
  1293.  
  1294. case self::COMM_VAR_RESETURL: 
  1295. /** 
  1296. * The reset-URL is only available in the password reset 
  1297. * email template. Reason is, that only ONE valid URL can 
  1298. * exist at a time, so if every email would contain a 
  1299. * reset URL it would invalidate all previous reset URLs. 
  1300. * 
  1301. * @since 1.0.2.3 
  1302. */ 
  1303. if ( self::COMM_TYPE_RESETPASSWORD == $this->type ) { 
  1304. $reset = $member->new_password_reset_key(); 
  1305. $var_value = $reset->url; 
  1306. break; 
  1307.  
  1308. case self::COMM_VAR_USER_DISPLAY_NAME: 
  1309. $var_value = $wp_user->display_name; 
  1310. break; 
  1311.  
  1312. case self::COMM_VAR_USER_FIRST_NAME: 
  1313. $var_value = $member->first_name; 
  1314. break; 
  1315.  
  1316. case self::COMM_VAR_USER_LAST_NAME: 
  1317. $var_value = $member->last_name; 
  1318. break; 
  1319.  
  1320. case self::COMM_VAR_NET_NAME: 
  1321. $var_value = get_site_option( 'site_name' ); 
  1322. break; 
  1323.  
  1324. case self::COMM_VAR_NET_URL: 
  1325. $var_value = get_site_option( 'siteurl' ); 
  1326. break; 
  1327.  
  1328. case self::COMM_VAR_MS_ACCOUNT_PAGE_URL: 
  1329. $var_value = sprintf( 
  1330. '<a href="%s">%s</a>',  
  1331. MS_Model_Pages::get_page_url( MS_Model_Pages::MS_PAGE_ACCOUNT ),  
  1332. __( 'account page', 'membership2' ) 
  1333. ); 
  1334. break; 
  1335.  
  1336. // Needs: $membership. 
  1337. case self::COMM_VAR_MS_NAME: 
  1338. if ( $membership && $membership->name ) { 
  1339. $var_value = $membership->name; 
  1340. break; 
  1341.  
  1342. // Needs: $membership. 
  1343. case self::COMM_VAR_MS_DESCRIPTION: 
  1344. if ( $membership && $membership->description ) { 
  1345. $var_value = $membership->get_description(); 
  1346. break; 
  1347.  
  1348. // Needs: $invoice. 
  1349. case self::COMM_VAR_MS_INVOICE: 
  1350. if ( $invoice ) { 
  1351. if ( $invoice->total > 0 || $invoice->uses_trial ) { 
  1352. $attr = array( 
  1353. 'post_id' => $invoice->id,  
  1354. 'pay_button' => 0,  
  1355. ); 
  1356. $scode = MS_Factory::load( 'MS_Controller_Shortcode' ); 
  1357. $var_value = $scode->membership_invoice( $attr ); 
  1358. break; 
  1359.  
  1360. // Needs: $subscription. 
  1361. case self::COMM_VAR_MS_REMAINING_DAYS: 
  1362. if ( $subscription ) { 
  1363. $days = $subscription->get_remaining_period( 0 ); 
  1364. $var_value = sprintf( 
  1365. __( '%s day%s', 'membership2' ),  
  1366. $days,  
  1367. abs( $days ) > 1 ? 's': '' 
  1368. ); 
  1369. break; 
  1370.  
  1371. // Needs: $subscription. 
  1372. case self::COMM_VAR_MS_REMAINING_TRIAL_DAYS: 
  1373. if ( $subscription ) { 
  1374. $days = $subscription->get_remaining_trial_period(); 
  1375. $var_value = sprintf( 
  1376. __( '%s day%s', 'membership2' ),  
  1377. $days,  
  1378. abs( $days ) > 1 ? 's': '' 
  1379. ); 
  1380. break; 
  1381.  
  1382. // Needs: $subscription. 
  1383. case self::COMM_VAR_MS_EXPIRY_DATE: 
  1384. if ( $subscription ) { 
  1385. $var_value = $subscription->expire_date; 
  1386. break; 
  1387.  
  1388. $comm_vars[ $key ] = apply_filters( 
  1389. 'ms_model_communication_send_message_comm_var-' . $key,  
  1390. $var_value,  
  1391. $this->type,  
  1392. $member,  
  1393. $subscription,  
  1394. $invoice 
  1395. ); 
  1396.  
  1397. return apply_filters( 
  1398. 'ms_model_communication_get_comm_vars',  
  1399. $comm_vars,  
  1400. $member 
  1401. ); 
  1402.  
  1403. /** 
  1404. * Get Email content type. 
  1405. * 
  1406. * Eg. text/html, text. 
  1407. * 
  1408. * @since 1.0.0 
  1409. * 
  1410. * @return string 
  1411. */ 
  1412. public function get_mail_content_type() { 
  1413. $this->content_type = apply_filters( 
  1414. 'ms_model_communication_set_html_content_type',  
  1415. 'text/html' 
  1416. ); 
  1417.  
  1418. return $this->content_type; 
  1419.  
  1420. /** 
  1421. * Validate specific property before set. 
  1422. * 
  1423. * @since 1.0.0 
  1424. * @param string $property The name of a property to associate. 
  1425. * @param mixed $value The value of a property. 
  1426. */ 
  1427. public function __set( $property, $value ) { 
  1428. switch ( $property ) { 
  1429. case 'type': 
  1430. if ( $this->is_valid_communication_type( $value ) ) { 
  1431. $this->$property = $value; 
  1432. break; 
  1433.  
  1434. case 'subject': 
  1435. $this->$property = sanitize_text_field( $value ); 
  1436. break; 
  1437.  
  1438. case 'cc_email': 
  1439. if ( is_email( $value ) ) { 
  1440. $this->$property = $value; 
  1441. break; 
  1442.  
  1443. case 'enabled': 
  1444. case 'cc_enabled': 
  1445. case 'override': 
  1446. $this->$property = lib3()->is_true( $value ); 
  1447. break; 
  1448.  
  1449. case 'period': 
  1450. $this->$property = $this->validate_period( $value ); 
  1451. break; 
  1452.  
  1453. case 'period_unit': 
  1454. $this->period['period_unit'] = $this->validate_period_unit( $value ); 
  1455. break; 
  1456.  
  1457. case 'period_type': 
  1458. $this->period['period_type'] = $this->validate_period_type( $value ); 
  1459. break; 
  1460.  
  1461. default: 
  1462. if ( property_exists( $this, $property ) ) { 
  1463. $this->$property = $value; 
  1464. break; 
  1465.  
  1466. do_action( 
  1467. 'ms_model_communication__set_after',  
  1468. $property,  
  1469. $value,  
  1470. $this 
  1471. ); 
  1472. }; 
.