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

  1. <?php 
  2. /** 
  3. * Transaction Log Model. 
  4. * 
  5. * Persisted by parent class MS_Model_CustomPostType. 
  6. * 
  7. * @since 1.0.1.0 
  8. * 
  9. * @package Membership2 
  10. * @subpackage Model 
  11. */ 
  12. class MS_Model_Transactionlog extends MS_Model_CustomPostType { 
  13.  
  14. /** 
  15. * Model custom post type. 
  16. * 
  17. * Both static and class property are used to handle php 5.2 limitations. 
  18. * 
  19. * @since 1.0.1.0 
  20. * 
  21. * @var string 
  22. */ 
  23. protected static $POST_TYPE = 'ms_transaction_log'; 
  24.  
  25. /** 
  26. * Timestamp of the transaction. 
  27. * 
  28. * @since 1.0.1. 
  29. * @var string 
  30. */ 
  31. protected $date = ''; 
  32.  
  33. /** 
  34. * The gateway that made the call. 
  35. * 
  36. * @since 1.0.1. 
  37. * @var string 
  38. */ 
  39. protected $gateway_id = ''; 
  40.  
  41. /** 
  42. * The transaction method. 
  43. * 
  44. * Possible methods are: 
  45. * "handle": IPN response 
  46. * "process": Process order (i.e. user comes from Payment screen) 
  47. * "request": Automatically request recurring payment 
  48. * 
  49. * @since 1.0.1.0 
  50. * @var string 
  51. */ 
  52. protected $method = ''; 
  53.  
  54. /** 
  55. * Indicator if the transaction was successfully processed by M2 
  56. * 
  57. * True means that an invoice was marked paid. 
  58. * False indicates an error or unknown input. 
  59. * NULL indicates a message that was processed but irrelevant. 
  60. * 
  61. * @since 1.0.1.0 
  62. * @var bool|null 
  63. */ 
  64. protected $success = null; 
  65.  
  66. /** 
  67. * Transaction state, similar to $success but as string. 
  68. * 
  69. * 'ok' means that an invoice was marked paid. 
  70. * 'err' indicates an error or unknown input. 
  71. * 'ignore' indicates a message that was processed but irrelevant. 
  72. * 
  73. * Note: This is the state of the original transaction, not the state that 
  74. * is displayed to the user. {@see $manual_state} 
  75. * 
  76. * @since 1.0.1.0 
  77. * @var string $state Access via $item->state (not $item->_state!) 
  78. */ 
  79. protected $_state = null; 
  80.  
  81. /** 
  82. * The subscription linked with the transaction. 
  83. * 
  84. * @since 1.0.1.0 
  85. * @var int 
  86. */ 
  87. protected $subscription_id = 0; 
  88.  
  89. /** 
  90. * The invoice linked with the transaction. 
  91. * 
  92. * @since 1.0.1.0 
  93. * @var int 
  94. */ 
  95. protected $invoice_id = 0; 
  96.  
  97. /** 
  98. * The member associated with the transaction. 
  99. * 
  100. * @since 1.0.1.0 
  101. * @var int 
  102. */ 
  103. protected $member_id = 0; 
  104.  
  105. /** 
  106. * The transaction amount reported by the gateway. 
  107. * 
  108. * @since 1.0.1.0 
  109. * @var int 
  110. */ 
  111. protected $amount = 0; 
  112.  
  113. /** 
  114. * The URL used to report the transaction. 
  115. * 
  116. * This is especially relevant for IPN messages (method "handle") 
  117. * 
  118. * @since 1.0.1.0 
  119. * @var string 
  120. */ 
  121. protected $url = ''; 
  122.  
  123. /** 
  124. * A collection of all POST parameters passed to the $url. 
  125. * 
  126. * @since 1.0.1.0 
  127. * @var array 
  128. */ 
  129. protected $post = null; 
  130.  
  131. /** 
  132. * A collection of all HTTP headers passed to the $url. 
  133. * 
  134. * @since 1.0.2.0 
  135. * @var array 
  136. */ 
  137. protected $headers = null; 
  138.  
  139. /** 
  140. * The manually overwritten state value. 
  141. * 
  142. * If this is empty then $state is the effective state value, otherwise this 
  143. * flag indicates the state that is displayed to the user. 
  144. * 
  145. * @since 1.0.1.0 
  146. * @var string 
  147. */ 
  148. protected $manual_state = ''; 
  149.  
  150. /** 
  151. * Timestamp of setting the $manual_state value. 
  152. * 
  153. * @since 1.0.1.0 
  154. * @var string 
  155. */ 
  156. protected $manual_date = ''; 
  157.  
  158. /** 
  159. * User who changed the $manual_state value. 
  160. * 
  161. * @since 1.0.1.0 
  162. * @var int 
  163. */ 
  164. protected $manual_user = 0; 
  165.  
  166. /** 
  167. * The external transaction ID provided by the gateway. 
  168. * 
  169. * @since 1.0.2.0 
  170. * @var string 
  171. */ 
  172. protected $external_id = ''; 
  173.  
  174.  
  175. // 
  176. // 
  177. // 
  178. // -------------------------------------------------------------- COLLECTION 
  179.  
  180.  
  181. /** 
  182. * Returns the post-type of the current object. 
  183. * 
  184. * @since 1.0.1.0 
  185. * @return string The post-type name. 
  186. */ 
  187. public static function get_post_type() { 
  188. return parent::_post_type( self::$POST_TYPE ); 
  189.  
  190. /** 
  191. * Get custom register post type args for this model. 
  192. * 
  193. * @since 1.0.1.0 
  194. * @return array Post Type details. 
  195. */ 
  196. public static function get_register_post_type_args() { 
  197. $args = array( 
  198. 'label' => __( 'Membership2 Transaction Logs', 'membership2' ),  
  199. 'supports' => array(),  
  200. 'hierarchical' => false,  
  201. 'public' => false,  
  202. 'show_ui' => false,  
  203. 'show_in_menu' => false,  
  204. 'show_in_admin_bar' => false,  
  205. 'show_in_nav_menus' => false,  
  206. 'can_export' => false,  
  207. 'has_archive' => false,  
  208. 'exclude_from_search' => true,  
  209. 'publicly_queryable' => false,  
  210. ); 
  211.  
  212. return apply_filters( 
  213. 'ms_customposttype_register_args',  
  214. $args,  
  215. self::get_post_type() 
  216. ); 
  217.  
  218. /** 
  219. * Get the total number of log entries. 
  220. * For list table pagination. 
  221. * 
  222. * @since 1.0.1.0 
  223. * 
  224. * @param array $args The default query args. 
  225. * @see @link http://codex.wordpress.org/Class_Reference/WP_Query 
  226. * @return int The total count. 
  227. */ 
  228. public static function get_item_count( $args = null ) { 
  229. $args = lib3()->array->get( $args ); 
  230. $args['posts_per_page'] = -1; 
  231. $items = self::get_items( $args ); 
  232.  
  233. $count = count( $items ); 
  234.  
  235. return apply_filters( 
  236. 'ms_model_transactionlog_get_item_count',  
  237. $count,  
  238. $args 
  239. ); 
  240.  
  241. /** 
  242. * Get transaction log items. 
  243. * 
  244. * @since 1.0.1.0 
  245. * 
  246. * @param $args The query post args. 
  247. * @see @link http://codex.wordpress.org/Class_Reference/WP_Query 
  248. * @return array List of transaction log items. 
  249. */ 
  250. public static function get_items( $args = null ) { 
  251. MS_Factory::select_blog(); 
  252. $args = self::get_query_args( $args ); 
  253. $query = new WP_Query( $args ); 
  254. MS_Factory::revert_blog(); 
  255.  
  256. $items = array(); 
  257.  
  258. foreach ( $query->posts as $post_id ) { 
  259. if ( ! get_post_meta( $post_id, 'method', true ) ) { 
  260. // The log entry is incomplete. Do not load it. 
  261. continue; 
  262.  
  263. $items[] = MS_Factory::load( 'MS_Model_Transactionlog', $post_id ); 
  264.  
  265. return apply_filters( 
  266. 'ms_model_transactionlog_get_items',  
  267. $items,  
  268. $args 
  269. ); 
  270.  
  271. /** 
  272. * Get WP_Query object arguments. 
  273. * 
  274. * Default search arguments for this custom post_type. 
  275. * 
  276. * @since 1.0.1.0 
  277. * 
  278. * @param $args The query post args 
  279. * @see @link http://codex.wordpress.org/Class_Reference/WP_Query 
  280. * @return array $args The parsed args. 
  281. */ 
  282. public static function get_query_args( $args ) { 
  283. $defaults = array( 
  284. 'post_type' => self::get_post_type(),  
  285. 'post_status' => 'any',  
  286. 'fields' => 'ids',  
  287. 'order' => 'DESC',  
  288. 'orderby' => 'ID',  
  289. 'posts_per_page' => 20,  
  290. ); 
  291.  
  292. if ( ! empty( $args['state'] ) ) { 
  293. $ids = self::get_state_ids( $args['state'] ); 
  294. if ( ! empty( $args['post__in'] ) ) { 
  295. $ids = array_intersect( $args['post__in'], $ids ); 
  296.  
  297. if ( $ids ) { 
  298. $args['post__in'] = $ids; 
  299. } else { 
  300. $args['post__in'] = array( 0 ); 
  301.  
  302. if ( ! empty( $args['source'] ) ) { 
  303. $ids = self::get_matched_ids( $args['source'][0], $args['source'][1] ); 
  304. if ( ! empty( $args['post__in'] ) ) { 
  305. $ids = array_intersect( $args['post__in'], $ids ); 
  306.  
  307. if ( $ids ) { 
  308. $args['post__in'] = $ids; 
  309. } else { 
  310. $args['post__in'] = array( 0 ); 
  311.  
  312. $args = wp_parse_args( $args, $defaults ); 
  313.  
  314. return apply_filters( 
  315. 'ms_model_transactionlog_get_item_args',  
  316. $args 
  317. ); 
  318.  
  319. /** 
  320. * Returns a list of post_ids that have the specified Transaction State. 
  321. * 
  322. * @since 1.0.1.0 
  323. * @param string $state A valid transaction state [err|ok|ignore]. 
  324. * @return array List of post_ids. 
  325. */ 
  326. static public function get_state_ids( $state ) { 
  327. global $wpdb; 
  328.  
  329. $sql = " 
  330. SELECT p.ID 
  331. FROM 
  332. {$wpdb->posts} p 
  333. LEFT JOIN {$wpdb->postmeta} state1 ON 
  334. state1.post_id = p.ID AND state1.meta_key = 'success' 
  335. LEFT JOIN {$wpdb->postmeta} state2 ON 
  336. state2.post_id = p.ID AND state2.meta_key = 'manual_state' 
  337. INNER JOIN {$wpdb->postmeta} method ON 
  338. method.post_id = p.ID AND method.meta_key = 'method' 
  339. WHERE 
  340. p.post_type = %s 
  341. AND LENGTH( method.meta_value ) > 0 
  342. "; 
  343.  
  344. switch ( $state ) { 
  345. case 'err': 
  346. $sql .= " 
  347. AND (state1.meta_value IS NULL OR state1.meta_value IN ('', '0', 'err')) 
  348. AND (state2.meta_value IS NULL OR state2.meta_value IN ('')) 
  349. "; 
  350. break; 
  351.  
  352. case 'ok': 
  353. $sql .= " 
  354. AND ( 
  355. state1.meta_value IN ('1', 'ok') 
  356. OR state2.meta_value IN ('1', 'ok') 
  357. "; 
  358. break; 
  359.  
  360. case 'ignore': 
  361. $sql .= " 
  362. AND ( 
  363. state1.meta_value IN ('ignore') 
  364. OR state2.meta_value IN ('ignore') 
  365. "; 
  366. break; 
  367.  
  368. $sql = $wpdb->prepare( $sql, self::get_post_type() ); 
  369. $ids = $wpdb->get_col( $sql ); 
  370.  
  371. if ( ! count( $ids ) ) { 
  372. $ids = array( 0 ); 
  373.  
  374. return $ids; 
  375.  
  376. /** 
  377. * Returns a list of post_ids that have the specified source_id. 
  378. * 
  379. * This tries to find transactions for imported subscriptions. 
  380. * 
  381. * @since 1.0.1.2 
  382. * @param string $source_id Subscription ID before import; i.e. original ID. 
  383. * @param string $source The import source. Currently supported: 'm1'. 
  384. * @return array List of post_ids. 
  385. */ 
  386. static public function get_matched_ids( $source_id, $source ) { 
  387. global $wpdb; 
  388.  
  389. $sql = " 
  390. SELECT p.ID 
  391. FROM 
  392. {$wpdb->posts} p 
  393. LEFT JOIN {$wpdb->postmeta} form ON 
  394. form.post_id = p.ID AND form.meta_key = 'post' 
  395. LEFT JOIN {$wpdb->postmeta} gateway ON 
  396. gateway.post_id = p.ID AND gateway.meta_key = 'gateway_id' 
  397. WHERE 
  398. p.post_type = %s 
  399. "; 
  400.  
  401. $source_int = intval( $source_id ); 
  402. $int_len = strlen( $source_int ); 
  403.  
  404. switch ( $source ) { 
  405. case 'm1': 
  406. $sql .= " 
  407. AND gateway.meta_value = 'paypalstandard' 
  408. AND form.meta_value LIKE '%%s:6:\"custom\";s:%%' 
  409. AND form.meta_value LIKE '%%:{$source_int}:%%' 
  410. "; 
  411. break; 
  412.  
  413. case 'pay_btn': 
  414. $sql .= " 
  415. AND gateway.meta_value = 'paypalstandard' 
  416. AND form.meta_value LIKE '%%s:6:\"btn_id\";s:{$int_len}:\"{$source_int}\";%%' 
  417. AND form.meta_value LIKE '%%s:11:\"payer_email\";%%' 
  418. "; 
  419. break; 
  420.  
  421. $sql = $wpdb->prepare( $sql, self::get_post_type() ); 
  422. $ids = $wpdb->get_col( $sql ); 
  423.  
  424. if ( ! count( $ids ) ) { 
  425. $ids = array( 0 ); 
  426.  
  427. return $ids; 
  428.  
  429. /** 
  430. * Checks if the specified transaction was already successfully processed 
  431. * to avoid duplicate payments. 
  432. * 
  433. * @since 1.0.2.0 
  434. * @param string $gateway The payment gateway ID. 
  435. * @param string $external_id The external transaction ID. 
  436. * @return bool True if the transaction was processed/paid already. 
  437. */ 
  438. static public function was_processed( $gateway, $external_id ) { 
  439. global $wpdb; 
  440.  
  441. $sql = " 
  442. SELECT COUNT(1) 
  443. FROM {$wpdb->posts} p 
  444. INNER JOIN {$wpdb->postmeta} gateway ON 
  445. gateway.post_id=p.ID AND gateway.meta_key='gateway_id' 
  446. INNER JOIN {$wpdb->postmeta} ext_id ON 
  447. ext_id.post_id=p.ID AND ext_id.meta_key='external_id' 
  448. LEFT JOIN {$wpdb->postmeta} state1 ON 
  449. state1.post_id = p.ID AND state1.meta_key = 'success' 
  450. LEFT JOIN {$wpdb->postmeta} state2 ON 
  451. state2.post_id = p.ID AND state2.meta_key = 'manual_state' 
  452. WHERE 
  453. p.post_type = %s 
  454. AND gateway.meta_value = %s 
  455. AND ext_id.meta_value = %s 
  456. AND ( 
  457. state1.meta_value IN ('1', 'ok') 
  458. OR state2.meta_value IN ('1', 'ok') 
  459. "; 
  460. $sql = $wpdb->prepare( 
  461. $sql,  
  462. self::get_post_type(),  
  463. $gateway,  
  464. $external_id 
  465. ); 
  466. $res = intval( $wpdb->get_var( $sql ) ); 
  467.  
  468. return $res > 0; 
  469.  
  470.  
  471. // 
  472. // 
  473. // 
  474. // ------------------------------------------------------------- SINGLE ITEM 
  475.  
  476.  
  477. /** 
  478. * Initializes variables right before saving the model. 
  479. * 
  480. * @since 1.0.1.0 
  481. */ 
  482. public function before_save() { 
  483. // Translate a boolean success value to a string. 
  484. if ( true === $this->success ) { 
  485. $this->success = 'ok'; 
  486. } elseif ( null === $this->success ) { 
  487. $this->success = 'ignore'; 
  488. } elseif ( false === $this->success ) { 
  489. $this->success = 'err'; 
  490.  
  491. if ( ! $this->id ) { 
  492. $this->url = lib3()->net->current_url(); 
  493. $this->post = $_POST; 
  494. $this->headers = $this->get_headers(); 
  495. $this->user_id = get_current_user_id(); 
  496. $this->title = 'Transaction Log'; 
  497.  
  498. /** 
  499. * Prepares an object after it was loaded from database. 
  500. * 
  501. * @since 1.0.1.0 
  502. */ 
  503. public function prepare_obj() { 
  504. $this->set_state( $this->success ); 
  505.  
  506. if ( ! $this->member_id ) { 
  507. if ( $this->invoice_id ) { 
  508. $invoice = MS_Factory::load( 'MS_Model_Invoice', $this->invoice_id ); 
  509. $this->member_id = $invoice->user_id; 
  510. } elseif ( MS_Gateway_Paypalstandard::ID == $this->gateway ) { 
  511. /** 
  512. * Migration logic for M1 IPN messages: 
  513. * M1 did use the "custom" field to link the transaction to a 
  514. * subscription. The custom field contains these details: 
  515. * timestamp : user_id : subscription_id : key 
  516. */ 
  517. if ( is_array( $this->post ) && ! empty( $this->post['custom'] ) ) { 
  518. $infos = explode( ':', $this->post['custom'] ); 
  519. if ( count( $infos ) > 2 && is_numeric( $infos[1] ) ) { 
  520. $this->member_id = intval( $infos[1] ); 
  521.  
  522. /** 
  523. * Populate custom fields from the wp_posts table. 
  524. * 
  525. * @since 1.0.1.0 
  526. * @param WP_Post $post The post object. 
  527. */ 
  528. public function load_post_data( $post ) { 
  529. $this->date = $post->post_date; 
  530.  
  531. /** 
  532. * Returns a list of all HTTP headers. 
  533. * 
  534. * @since 1.0.1.2 
  535. * @return array List of all incoming HTTP headers. 
  536. */ 
  537. protected function get_headers() { 
  538. $headers = array(); 
  539.  
  540. if ( function_exists( 'getallheaders' ) ) { 
  541. $headers = getallheaders(); 
  542. } else { 
  543. foreach ( $_SERVER as $key => $value ) { 
  544. if ( 'HTTP_' == substr( $key, 0, 5 ) ) { 
  545. $key = str_replace( '_', ' ', substr( $key, 5 ) ); 
  546. $key = str_replace( ' ', '-', ucwords( strtolower( $key ) ) ); 
  547. $headers[ $key ] = $value; 
  548.  
  549. return $headers; 
  550.  
  551. /** 
  552. * Sets the manual-state value of the transaction log entry. 
  553. * 
  554. * @since 1.0.0 
  555. * @param string $state The new state of the item. 
  556. * @return bool True on success. 
  557. */ 
  558. public function manual_state( $state ) { 
  559. if ( 'err' != $this->_state ) { 
  560. // Not allowed: Only error state can be manually corrected. 
  561. return false; 
  562.  
  563. switch ( $state ) { 
  564. case 'ignore': 
  565. if ( $this->manual_state ) { 
  566. // Not allowed: Manual state was defined already. 
  567. return false; 
  568. break; 
  569.  
  570. case 'clear': 
  571. if ( 'ignore' != $this->manual_state ) { 
  572. // Not allowed: Only "ingored" state can be cleared. 
  573. return false; 
  574. break; 
  575.  
  576. case 'ok': 
  577. if ( $this->manual ) { 
  578. // Not allowed: Manual state is already defined. 
  579. return false; 
  580. if ( ! $this->invoice_id || ! $this->subscription_id ) { 
  581. // Not allowed: Required data is missing for OK status. 
  582. return false; 
  583. break; 
  584.  
  585. default: 
  586. // Not allowed: Unknown state. 
  587. return false; 
  588.  
  589. if ( 'clear' == $state ) { 
  590. $this->manual_state = ''; 
  591. $this->manual_date = ''; 
  592. $this->manual_user = 0; 
  593. } else { 
  594. $this->manual_state = $state; 
  595. $this->manual_date = MS_Helper_Period::current_time(); 
  596. $this->manual_user = get_current_user_id(); 
  597. return true; 
  598.  
  599. /** 
  600. * Returns the WP_User object for the manual user. 
  601. * 
  602. * @since 1.0.1.0 
  603. * @return WP_User 
  604. */ 
  605. public function get_manual_user() { 
  606. $user = new WP_User( $this->manual_user ); 
  607. return $user; 
  608.  
  609. /** 
  610. * Returns the Member object associated with this transaction. 
  611. * 
  612. * @since 1.0.1.0 
  613. * @return MS_Model_Member 
  614. */ 
  615. public function get_member() { 
  616. return MS_Factory::load( 'MS_Model_Member', $this->member_id ); 
  617.  
  618. /** 
  619. * Returns the Invoice model linked with the transaction. 
  620. * 
  621. * @since 1.0.1.0 
  622. * @return bool|MS_Model_Invoice 
  623. */ 
  624. public function get_invoice() { 
  625. $result = false; 
  626.  
  627. if ( $this->invoice_id ) { 
  628. $invoice = MS_Factory::load( 'MS_Model_Invoice', $this->invoice_id ); 
  629. if ( $invoice->id == $this->invoice_id ) { 
  630. $result = $invoice; 
  631.  
  632. return $result; 
  633.  
  634. /** 
  635. * Updates the subscription_id and member_id based on the specified ID. 
  636. * 
  637. * @since 1.0.1.0 
  638. * @param int $id A valid subscription ID. 
  639. */ 
  640. protected function set_subscription( $id ) { 
  641. $subscription = MS_Factory::load( 'MS_Model_Relationship', $id ); 
  642. $this->subscription_id = $subscription->id; 
  643. $this->member_id = $subscription->user_id; 
  644.  
  645. /** 
  646. * Updates the invoice_id, subscription_id and member_id based on the 
  647. * specified ID. 
  648. * 
  649. * @since 1.0.1.0 
  650. * @param int $id A valid invoice ID. 
  651. */ 
  652. protected function set_invoice( $id ) { 
  653. $invoice = MS_Factory::load( 'MS_Model_Invoice', $id ); 
  654. $this->invoice_id = $invoice->id; 
  655. $this->subscription_id = $invoice->ms_relationship_id; 
  656. $this->member_id = $invoice->user_id; 
  657.  
  658. /** 
  659. * Updates the state and success properties of the object. 
  660. * 
  661. * @since 1.0.1.0 
  662. * @param mixed $value The new state value 
  663. */ 
  664. protected function set_state( $value ) { 
  665. switch ( $value ) { 
  666. case 'ok': 
  667. $this->_state = $value; 
  668. $this->success = true; 
  669. break; 
  670.  
  671. case 'ignore': 
  672. $this->_state = $value; 
  673. $this->success = null; 
  674. break; 
  675.  
  676. case 'err': 
  677. $this->_state = $value; 
  678. $this->success = false; 
  679. break; 
  680.  
  681. case true: 
  682. $this->_state = 'ok'; 
  683. $this->success = $value; 
  684. break; 
  685.  
  686. case false: 
  687. $this->_state = 'err'; 
  688. $this->success = $value; 
  689. break; 
  690.  
  691. case null: 
  692. $this->_state = 'ignore'; 
  693. $this->success = 'ignore'; 
  694. break; 
  695.  
  696. default: 
  697. // Unrecognized values are not saved. 
  698.  
  699. /** 
  700. * Returns property associated with the render. 
  701. * 
  702. * @since 1.0.1.0 
  703. * @internal 
  704. * @param string $property The name of a property. 
  705. * @return mixed Returns mixed value of a property or NULL if a property doesn't exist. 
  706. */ 
  707. public function __get( $property ) { 
  708. $value = null; 
  709.  
  710. switch ( $property ) { 
  711. case 'state': 
  712. if ( $this->manual_state ) { 
  713. $value = $this->manual_state; 
  714. } else { 
  715. $value = $this->_state; 
  716. break; 
  717.  
  718. case 'is_manual': 
  719. $value = ! ! $this->manual_state; 
  720. break; 
  721.  
  722. default: 
  723. if ( property_exists( $this, $property ) ) { 
  724. $value = $this->$property; 
  725. break; 
  726.  
  727. return apply_filters( 
  728. 'ms_model_transactionlog__get',  
  729. $value,  
  730. $property,  
  731. $this 
  732. ); 
  733.  
  734. /** 
  735. * Set specific property. 
  736. * 
  737. * @since 1.0.1.0 
  738. * @internal 
  739. * @param string $property The name of a property to associate. 
  740. * @param mixed $value The value of a property. 
  741. */ 
  742. public function __set( $property, $value ) { 
  743. switch ( $property ) { 
  744. case 'state': 
  745. case 'success': 
  746. $this->set_state( $value ); 
  747. break; 
  748.  
  749. case 'invoice_id': 
  750. $this->set_invoice( $value ); 
  751. break; 
  752.  
  753. case 'subscription_id': 
  754. $this->set_subscription( $value ); 
  755. break; 
  756.  
  757. default: 
  758. if ( property_exists( $this, $property ) ) { 
  759. $this->$property = $value; 
  760. break; 
  761.  
  762. do_action( 
  763. 'ms_model_transactionlog__set_after',  
  764. $property,  
  765. $value,  
  766. $this 
  767. ); 
.