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