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

  1. <?php 
  2. /** 
  3. * Abstract Custom Post Type model. 
  4. * 
  5. * Persists data into wp_post and wp_postmeta 
  6. * 
  7. * @since 1.0.0 
  8. * 
  9. * @package Membership2 
  10. * @subpackage Model 
  11. */ 
  12. class MS_Model_CustomPostType extends MS_Model { 
  13.  
  14. /** 
  15. * Model custom post type. 
  16. * 
  17. * Both static and class property are used to handle php 5.2 limitations. 
  18. * Override this value in child object. 
  19. * 
  20. * @since 1.0.0 
  21. * @var string 
  22. */ 
  23. protected static $POST_TYPE = ''; 
  24.  
  25. /** 
  26. * ID of the model object. 
  27. * 
  28. * Saved as WP post ID. 
  29. * 
  30. * @since 1.0.0 
  31. * 
  32. * @var int 
  33. */ 
  34. protected $id = 0; 
  35.  
  36. /** 
  37. * Model name (this is the post slug) 
  38. * 
  39. * @since 1.0.0 
  40. * 
  41. * @var string 
  42. */ 
  43. protected $name = ''; 
  44.  
  45. /** 
  46. * Model title. 
  47. * 
  48. * Saved in $post->post_title. 
  49. * 
  50. * @since 1.0.0 
  51. * 
  52. * @var string 
  53. */ 
  54. protected $title = ''; 
  55.  
  56. /** 
  57. * Model description. 
  58. * 
  59. * Saved in $post->post_content and $post->excerpt. 
  60. * 
  61. * @since 1.0.0 
  62. * 
  63. * @var string 
  64. */ 
  65. protected $description = ''; 
  66.  
  67. /** 
  68. * The user ID of the owner. 
  69. * 
  70. * Saved in $post->post_author 
  71. * 
  72. * @since 1.0.0 
  73. * 
  74. * @var int 
  75. */ 
  76. protected $user_id = 0; 
  77.  
  78. /** 
  79. * The last modified date. 
  80. * 
  81. * Saved in $post->post_modified 
  82. * 
  83. * @since 1.0.0 
  84. * 
  85. * @var string 
  86. */ 
  87. protected $post_modified = ''; 
  88.  
  89. /** 
  90. * Custom data can be used by other plugins via the set_custom_data() and 
  91. * get_custom_data() functions. 
  92. * 
  93. * This can be used to store data that other plugins use to store object 
  94. * related information, like affiliate options for a membership, etc. 
  95. * 
  96. * @since 1.0.0 
  97. * 
  98. * @var array 
  99. */ 
  100. protected $custom_data = array(); 
  101.  
  102. /** 
  103. * Not persisted fields. 
  104. * 
  105. * @since 1.0.0 
  106. * 
  107. * @var array 
  108. */ 
  109. static public $ignore_fields = array(); 
  110.  
  111. /** 
  112. * Validates the object right after it was loaded/initialized. 
  113. * 
  114. * We ensure that the custom_data field is an array. 
  115. * 
  116. * @since 1.0.0 
  117. */ 
  118. public function prepare_obj() { 
  119. parent::prepare_obj(); 
  120.  
  121. if ( ! is_array( $this->custom_data ) ) { 
  122. $this->custom_data = array(); 
  123.  
  124. /** 
  125. * Save content in wp tables (wp_post and wp_postmeta). 
  126. * 
  127. * Update WP cache. 
  128. * 
  129. * @since 1.0.0 
  130. */ 
  131. public function save() { 
  132. MS_Factory::select_blog(); 
  133. $this->before_save(); 
  134.  
  135. $this->post_modified = gmdate( 'Y-m-d H:i:s' ); 
  136. $class = get_class( $this ); 
  137.  
  138. /** 
  139. * Serialize data that is later saved to the postmeta table. 
  140. * 
  141. * While data is serialized it can also modify the model data before 
  142. * writing it to the posts table. 
  143. */ 
  144. $data = MS_Factory::serialize_model( $this ); 
  145.  
  146. $post = array( 
  147. 'comment_status' => 'closed',  
  148. 'ping_status' => 'closed',  
  149. 'post_author' => $this->user_id,  
  150. 'post_content' => $this->description,  
  151. 'post_excerpt' => $this->description,  
  152. 'post_name' => sanitize_text_field( $this->name ),  
  153. 'post_status' => 'private',  
  154. 'post_title' => sanitize_title( ! empty( $this->title ) ? $this->title : $this->name ),  
  155. 'post_type' => $this->get_post_type(),  
  156. 'post_modified' => $this->post_modified,  
  157. ); 
  158.  
  159. /** 
  160. * Give child classes an easy way to modify the post and meta data right 
  161. * before it is saved. 
  162. * 
  163. * @since 1.0.1.0 
  164. */ 
  165. $post = $this->save_post_data( $post ); 
  166. $data = $this->save_meta_data( $data ); 
  167.  
  168. if ( empty( $this->id ) ) { 
  169. $this->id = wp_insert_post( $post ); 
  170. } else { 
  171. $post[ 'ID' ] = $this->id; 
  172. wp_update_post( $post ); 
  173.  
  174. // We first remove any metadata of our custom post type that is not 
  175. // contained in the serialized data collection. 
  176. $this->clean_metadata( array_keys( $data ) ); 
  177.  
  178. // Then we update all meta fields that are inside the collection 
  179. foreach ( $data as $field => $val ) { 
  180. update_post_meta( $this->id, $field, $val ); 
  181.  
  182. wp_cache_set( $this->id, $this, $class ); 
  183. $this->after_save(); 
  184. MS_Factory::revert_blog(); 
  185.  
  186. global $wp_current_filter; 
  187. if ( ! in_array( 'ms_saved_' . $class, $wp_current_filter ) ) { 
  188. /** 
  189. * Action triggered after a custom post type model was saved to 
  190. * database. 
  191. * 
  192. * @since 1.0.0 
  193. */ 
  194. do_action( 'ms_saved_' . $class, $this ); 
  195.  
  196. /** 
  197. * Prepare the post data right before it is saved to the wp_posts table. 
  198. * 
  199. * @see self::save() 
  200. * @since 1.0.1.0 
  201. * @param array $post Data collection passed to wp_update_post(). 
  202. * @return array Data collection passed to wp_update_post(). 
  203. */ 
  204. protected function save_post_data( $post ) { 
  205. return $post; 
  206.  
  207. /** 
  208. * Prepare the meta data right before it is saved to the wp_postmeta table. 
  209. * 
  210. * @see self::save() 
  211. * @since 1.0.1.0 
  212. * @param array $data Key-Value pairs that represent metadata. 
  213. * @return array Key-Value pairs that represent metadata. 
  214. */ 
  215. protected function save_meta_data( $data ) { 
  216. return $data; 
  217.  
  218. /** 
  219. * Populate the model with custom data from the wp_posts table. 
  220. * 
  221. * @see MS_Factory::load_from_wp_custom_post_type() 
  222. * @since 1.0.1.0 
  223. * @param array $post Data collection passed to wp_update_post(). 
  224. */ 
  225. public function load_post_data( $post ) { 
  226.  
  227. /** 
  228. * Populate the model with custom data from the wp_postmeta table. 
  229. * 
  230. * @see MS_Factory::load_from_wp_custom_post_type() 
  231. * @since 1.0.1.0 
  232. * @param array $data Key-Value pairs that represent metadata. 
  233. */ 
  234. public function load_meta_data( $data ) { 
  235.  
  236. /** 
  237. * Delete post from wp table 
  238. * 
  239. * @since 1.0.0 
  240. * 
  241. * @return bool 
  242. */ 
  243. public function delete() { 
  244. MS_Factory::select_blog(); 
  245. do_action( 'MS_Model_CustomPostType_delete_before', $this ); 
  246. $res = false; 
  247.  
  248. if ( ! empty( $this->id ) ) { 
  249. $res = ( false !== wp_delete_post( $this->id, true ) ); 
  250.  
  251. do_action( 'MS_Model_CustomPostType_delete_after', $this, $res ); 
  252. MS_Factory::revert_blog(); 
  253. return $res; 
  254.  
  255. /** 
  256. * Removes all meta fields, except the ones that are specified in the 
  257. * second parameter. 
  258. * 
  259. * @since 1.0.0 
  260. * @param array $data_to_keep List of meta-fields to keep (field-names) 
  261. */ 
  262. private function clean_metadata( $data_to_keep ) { 
  263. global $wpdb; 
  264.  
  265. $sql = "SELECT meta_key FROM {$wpdb->postmeta} WHERE post_id = %s;"; 
  266. $sql = $wpdb->prepare( $sql, $this->id ); 
  267. $all_fields = $wpdb->get_col( $sql ); 
  268.  
  269. $remove = array_diff( $all_fields, $data_to_keep ); 
  270.  
  271. $remove = apply_filters( 
  272. 'ms_model_clean_metadata',  
  273. $remove,  
  274. $all_fields,  
  275. $this->id,  
  276. $data_to_keep 
  277. ); 
  278.  
  279. foreach ( $remove as $key ) { 
  280. delete_post_meta( $this->id, $key ); 
  281.  
  282. /** 
  283. * Get custom register post type args for this model. 
  284. * 
  285. * @since 1.0.0 
  286. */ 
  287. public static function get_register_post_type_args() { 
  288. return apply_filters( 
  289. 'ms_customposttype_register_args',  
  290. array() 
  291. ); 
  292.  
  293. /** 
  294. * Check to see if the post is currently being edited. 
  295. * 
  296. * @see wp_check_post_lock. 
  297. * 
  298. * @since 1.0.0 
  299. * 
  300. * @return boolean True if locked. 
  301. */ 
  302. public function check_object_lock() { 
  303. MS_Factory::select_blog(); 
  304. $locked = false; 
  305.  
  306. if ( $this->is_valid() 
  307. && $lock = get_post_meta( $this->id, '_ms_edit_lock', true ) 
  308. ) { 
  309. $time = $lock; 
  310. $time_window = apply_filters( 
  311. 'MS_Model_CustomPostType_check_object_lock_window',  
  312. 150 
  313. ); 
  314. if ( $time && $time > time() - $time_window ) { 
  315. $locked = true; 
  316.  
  317. MS_Factory::revert_blog(); 
  318. return apply_filters( 
  319. 'MS_Model_CustomPostType_check_object_lock',  
  320. $locked,  
  321. $this 
  322. ); 
  323.  
  324. /** 
  325. * Mark the object as currently being edited. 
  326. * 
  327. * Based in the wp_set_post_lock 
  328. * 
  329. * @since 1.0.0 
  330. * 
  331. * @return bool|int 
  332. */ 
  333. public function set_object_lock() { 
  334. MS_Factory::select_blog(); 
  335. $lock = false; 
  336.  
  337. if ( $this->is_valid() ) { 
  338. $lock = apply_filters( 
  339. 'MS_Model_CustomPostType_set_object_lock',  
  340. time() 
  341. ); 
  342. update_post_meta( $this->id, '_ms_edit_lock', $lock ); 
  343.  
  344. MS_Factory::revert_blog(); 
  345. return apply_filters( 
  346. 'MS_Model_CustomPostType_set_object_lock',  
  347. $lock,  
  348. $this 
  349. ); 
  350.  
  351. /** 
  352. * Delete object lock. 
  353. * 
  354. * @since 1.0.0 
  355. */ 
  356. public function delete_object_lock() { 
  357. MS_Factory::select_blog(); 
  358. if ( $this->is_valid() ) { 
  359. update_post_meta( $this->id, '_ms_edit_lock', '' ); 
  360.  
  361. do_action( 'MS_Model_CustomPostType_delete_object_lock', $this ); 
  362. MS_Factory::revert_blog(); 
  363.  
  364. /** 
  365. * Check if the current post type exists. 
  366. * 
  367. * @since 1.0.0 
  368. * 
  369. * @return boolean True if valid. 
  370. */ 
  371. public function is_valid() { 
  372. $valid = false; 
  373.  
  374. if ( $this->id > 0 ) { 
  375. $valid = true; 
  376.  
  377. return apply_filters( 
  378. 'MS_Model_CustomPostType_is_valid',  
  379. $valid,  
  380. $this 
  381. ); 
  382.  
  383. /** 
  384. * Either creates or updates the value of a custom data field. 
  385. * 
  386. * Note: Remember to prefix the $key with a unique string to prevent 
  387. * conflicts with other plugins that also use this function. 
  388. * 
  389. * @since 1.0.0 
  390. * @api 
  391. * 
  392. * @param string $key The field-key. 
  393. * @param mixed $value The new value to assign to the field. 
  394. */ 
  395. public function set_custom_data( $key, $value ) { 
  396. $this->custom_data[ $key ] = $value; 
  397.  
  398. /** 
  399. * Removes a custom data field from this object. 
  400. * 
  401. * @since 1.0.0 
  402. * @api 
  403. * 
  404. * @param string $key The field-key. 
  405. */ 
  406. public function delete_custom_data( $key ) { 
  407. unset( $this->custom_data[ $key ] ); 
  408.  
  409. /** 
  410. * Returns the value of a custom data field. 
  411. * 
  412. * @since 1.0.0 
  413. * @api 
  414. * 
  415. * @param string $key The field-key. 
  416. * @return mixed The value that was previously assigned to the custom field 
  417. * or false if no value was set for the field. 
  418. */ 
  419. public function get_custom_data( $key ) { 
  420. $res = false; 
  421. if ( isset( $this->custom_data[ $key ] ) ) { 
  422. $res = $this->custom_data[ $key ]; 
  423. return $res; 
  424.  
  425. /** 
  426. * Returns the post-type of the current object. 
  427. * 
  428. * @since 1.0.0 
  429. * @return string The post-type name. 
  430. */ 
  431. protected static function _post_type( $orig_posttype ) { 
  432. // Post-type is always lower case. 
  433. $posttype = strtolower( substr( $orig_posttype, 0, 20 ) ); 
  434.  
  435. // Network-wide IS PRO ONLY! 
  436.  
  437. return $posttype; 
.