Mixin_CustomPost_DataMapper_Driver

Provides instance methods for C_CustomPost_DataMapper_Driver.

Defined (1)

The class is defined in the following location(s).

/products/photocrati_nextgen/modules/datamapper/package.module.datamapper.php  
  1. class Mixin_CustomPost_DataMapper_Driver extends Mixin 
  2. /** 
  3. * Returns a list of querable table columns for posts 
  4. * @return array 
  5. */ 
  6. function _get_querable_table_columns() 
  7. return array('name', 'author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count'); 
  8. /** 
  9. * Used to select which fields should be returned. NOT currently used by 
  10. * this implementation of the datamapper driver 
  11. * @param type $fields 
  12. * @return C_DataMapper_Driver_Base 
  13. */ 
  14. function select($fields = '*') 
  15. $this->object->_query_args = array('post_type' => $this->object->get_object_name(), 'paged' => FALSE, 'fields' => $fields, 'post_status' => 'any', 'datamapper' => TRUE, 'posts_per_page' => -1, 'is_select' => TRUE, 'is_delete' => FALSE); 
  16. return $this->object; 
  17. /** 
  18. * Specifies an order clause 
  19. * @param type $order_by 
  20. * @param type $direction 
  21. * @return C_DataMapper_Driver_Base 
  22. */ 
  23. function order_by($order_by, $direction = 'ASC') 
  24. // Make an exception for the rand() method 
  25. $order_by = preg_replace("/rand\\(\\s*\\)/", 'rand', $order_by); 
  26. if (in_array($order_by, $this->object->_get_querable_table_columns())) { 
  27. $this->object->_query_args['orderby'] = $order_by; 
  28. } else { 
  29. // ordering by a meta value 
  30. $this->object->_query_args['orderby'] = 'meta_value'; 
  31. $this->object->_query_args['meta_key'] = $order_by; 
  32. $this->object->_query_args['order'] = $direction; 
  33. return $this->object; 
  34. /** 
  35. * Specifies a limit and optional offset 
  36. * @param integer $max 
  37. * @param integer $offset 
  38. * @return C_DataMapper_Driver_Base 
  39. */ 
  40. function limit($max, $offset = FALSE) 
  41. if ($max) { 
  42. $this->object->_query_args['paged'] = TRUE; 
  43. if ($offset) { 
  44. $this->object->_query_args['offset'] = $offset; 
  45. } else { 
  46. unset($this->object->_query_args['offset']); 
  47. $this->object->_query_args['posts_per_page'] = $max; 
  48. return $this->object; 
  49. /** 
  50. * Specifies a list of columns to group by 
  51. * @param array|string $columns 
  52. */ 
  53. function group_by($columns = array()) 
  54. if (!isset($this->object->_query_args['group_by_columns'])) { 
  55. $this->object->_query_args['group_by_columns'] = $columns; 
  56. } else { 
  57. $this->object->_query_args['group_by_columns'] = array_merge($this->object->_query_args['group_by_columns'], $columns); 
  58. return $this->object; 
  59. /** 
  60. * Adds a WP_Query where clause 
  61. * @param array $where_clauses 
  62. * @param string $join 
  63. */ 
  64. function _add_where_clause($where_clauses, $join) 
  65. foreach ($where_clauses as $clause) { 
  66. // $clause => array( 
  67. // 'column' => 'ID',  
  68. // 'value' => 1210,  
  69. // 'compare' => '=' 
  70. // ) 
  71. // Determine where what the where clause is comparing 
  72. switch ($clause['column']) { 
  73. case 'author': 
  74. case 'author_id': 
  75. $this->object->_query_args['author'] = $clause['value']; 
  76. break; 
  77. case 'author_name': 
  78. $this->object->_query_args['author_name'] = $clause['value']; 
  79. break; 
  80. case 'cat': 
  81. case 'cat_id': 
  82. case 'category_id': 
  83. switch ($clause['compare']) { 
  84. case '=': 
  85. case 'BETWEEN': 
  86. case 'IN': 
  87. if (!isset($this->object->_query_args['category__in'])) { 
  88. $this->object->_query_args['category__in'] = array(); 
  89. $this->object->_query_args['category__in'][] = $clause['value']; 
  90. break; 
  91. case '!=': 
  92. case 'NOT BETWEEN': 
  93. case 'NOT IN': 
  94. if (!isset($this->object->_query_args['category__not_in'])) { 
  95. $this->object->_query_args['category__not_in'] = array(); 
  96. $this->object->_query_args['category__not_in'][] = $clause['value']; 
  97. break; 
  98. break; 
  99. case 'category_name': 
  100. $this->object->_query_args['category_name'] = $clause['value']; 
  101. break; 
  102. case 'post_id': 
  103. case $this->object->get_primary_key_column(): 
  104. switch ($clause['compare']) { 
  105. case '=': 
  106. case 'IN': 
  107. case 'BETWEEN': 
  108. if (!isset($this->object->_query_args['post__in'])) { 
  109. $this->object->_query_args['post__in'] = array(); 
  110. $this->object->_query_args['post__in'][] = $clause['value']; 
  111. break; 
  112. default: 
  113. if (!isset($this->object->_query_args['post__not_in'])) { 
  114. $this->object->_query_args['post__not_in'] = array(); 
  115. $this->object->_query_args['post__not_in'][] = $clause['value']; 
  116. break; 
  117. break; 
  118. case 'pagename': 
  119. case 'postname': 
  120. case 'page_name': 
  121. case 'post_name': 
  122. if ($clause['compare'] == 'LIKE') { 
  123. $this->object->_query_args['page_name__like'] = $clause['value']; 
  124. } elseif ($clause['compare'] == '=') { 
  125. $this->object->_query_args['pagename'] = $clause['value']; 
  126. } elseif ($clause['compare'] == 'IN') { 
  127. $this->object->_query_args['page_name__in'] = $clause['value']; 
  128. break; 
  129. case 'post_title': 
  130. // Post title uses custom WHERE clause 
  131. if ($clause['compare'] == 'LIKE') { 
  132. $this->object->_query_args['post_title__like'] = $clause['value']; 
  133. } else { 
  134. $this->object->_query_args['post_title'] = $clause['value']; 
  135. break; 
  136. default: 
  137. // Must be metadata 
  138. $clause['key'] = $clause['column']; 
  139. unset($clause['column']); 
  140. // Convert values to array, when required 
  141. if (in_array($clause['compare'], array('IN', 'BETWEEN'))) { 
  142. $clause['value'] = explode(', ', $clause['value']); 
  143. foreach ($clause['value'] as &$val) { 
  144. if (!is_numeric($val)) { 
  145. // In the _parse_where_clause() method, we 
  146. // quote the strings and add slashes 
  147. $val = stripslashes($val); 
  148. $val = substr($val, 1, strlen($val) - 2); 
  149. if (!isset($this->object->_query_args['meta_query'])) { 
  150. $this->object->_query_args['meta_query'] = array(); 
  151. $this->object->_query_args['meta_query'][] = $clause; 
  152. break; 
  153. // If any where clauses have been added, specify how the conditions 
  154. // will be conbined/joined 
  155. if (isset($this->object->_query_args['meta_query'])) { 
  156. $this->object->_query_args['meta_query']['relation'] = $join; 
  157. /** 
  158. * Destroys/deletes an entity from the database 
  159. * @param stdObject|C_DataMapper_Model $entity 
  160. * @return type 
  161. */ 
  162. function destroy($entity, $skip_trash = TRUE) 
  163. $retval = FALSE; 
  164. $key = $this->object->get_primary_key_column(); 
  165. // Find the id of the entity 
  166. if (is_object($entity) && isset($entity->{$key})) { 
  167. $id = (int) $entity->{$key}; 
  168. } else { 
  169. $id = (int) $entity; 
  170. // If we have an ID, then delete the post 
  171. if (is_integer($id)) { 
  172. // TODO: We assume that we can skip the trash. Is that correct? 
  173. // FYI, Deletes postmeta as wells 
  174. if (is_object(wp_delete_post($id, TRUE))) { 
  175. $retval = TRUE; 
  176. return $retval; 
  177. /** 
  178. * Converts a post to an entity 
  179. * @param \stdClass $post 
  180. * @param boolean $model 
  181. * @return \stdClass 
  182. */ 
  183. function convert_post_to_entity($post, $model = FALSE) 
  184. $entity = new stdClass(); 
  185. // Unserialize the post_content_filtered field 
  186. if (is_string($post->post_content_filtered)) { 
  187. if ($post_content = $this->object->unserialize($post->post_content_filtered)) { 
  188. foreach ($post_content as $key => $value) { 
  189. $post->{$key} = $value; 
  190. // Unserialize the post content field 
  191. if (is_string($post->post_content)) { 
  192. if ($post_content = $this->object->unserialize($post->post_content)) { 
  193. foreach ($post_content as $key => $value) { 
  194. $post->{$key} = $value; 
  195. // Copy post fields to entity 
  196. unset($post->post_content); 
  197. unset($post->post_content_filtered); 
  198. foreach ($post as $key => $value) { 
  199. $entity->{$key} = $value; 
  200. $this->object->_convert_to_entity($entity); 
  201. return $model ? $this->object->convert_to_model($entity) : $entity; 
  202. /** 
  203. * Converts an entity to a post 
  204. * @param type $entity 
  205. * @return type 
  206. */ 
  207. function _convert_entity_to_post($entity) 
  208. // Was a model passed instead of an entity? 
  209. $post = $entity; 
  210. if (!$entity instanceof stdClass) { 
  211. $post = $entity->get_entity(); 
  212. // Create the post content 
  213. $post_content = clone $post; 
  214. foreach ($this->object->_table_columns as $column) { 
  215. unset($post_content->{$column}); 
  216. unset($post->id_field); 
  217. unset($post->post_content_filtered); 
  218. unset($post->post_content); 
  219. $post->post_content = $this->object->serialize($post_content); 
  220. $post->post_content_filtered = $post->post_content; 
  221. $post->post_type = $this->object->get_object_name(); 
  222. // Sometimes an entity can contain a data stored in an array or object 
  223. // Those will be removed from the post, and serialized in the 
  224. // post_content field 
  225. foreach ($post as $key => $value) { 
  226. if (in_array(strtolower(gettype($value)), array('object', 'array'))) { 
  227. unset($post->{$key}); 
  228. // A post required a title 
  229. if (!property_exists($post, 'post_title')) { 
  230. $post->post_title = $this->object->get_post_title($post); 
  231. // A post also requires an excerpt 
  232. if (!property_exists($post, 'post_excerpt')) { 
  233. $post->post_excerpt = $this->object->get_post_excerpt($post); 
  234. return $post; 
  235. /** 
  236. * Returns the WordPress database class 
  237. * @global wpdb $wpdb 
  238. * @return wpdb 
  239. */ 
  240. function _wpdb() 
  241. global $wpdb; 
  242. return $wpdb; 
  243. /** 
  244. * Flush and update all postmeta for a particular post 
  245. * @param int $post_id 
  246. */ 
  247. function _flush_and_update_postmeta($post_id, $entity, $omit = array()) 
  248. // We need to insert post meta data for each property 
  249. // Unfortunately, that means flushing all existing postmeta 
  250. // and then inserting new values. Depending on the number of 
  251. // properties, this could be slow. So, we directly access the database 
  252. /** @var $wpdb wpdb */ 
  253. global $wpdb; 
  254. if (!is_array($omit)) { 
  255. $omit = array($omit); 
  256. // By default, we omit creating meta values for columns in the posts table 
  257. $omit = array_merge($omit, $this->object->_table_columns); 
  258. // Delete the existing meta values 
  259. $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE post_id = %s", $post_id)); 
  260. // Create query for new meta values 
  261. $sql_parts = array(); 
  262. foreach ($entity as $key => $value) { 
  263. if (in_array($key, $omit)) { 
  264. continue; 
  265. if (is_array($value) or is_object($value)) { 
  266. $value = $this->object->serialize($value); 
  267. $sql_parts[] = $wpdb->prepare("(%s, %s, %s)", $post_id, $key, $value); 
  268. $wpdb->query("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES " . implode(', ', $sql_parts)); 
  269. /** 
  270. * Saves an entity to the database 
  271. * @param stdObject $entity 
  272. */ 
  273. function _save_entity($entity) 
  274. $post = $this->object->_convert_entity_to_post($entity); 
  275. $primary_key = $this->object->get_primary_key_column(); 
  276. // TODO: unsilence this. Wordpress 3.9-beta2 is generating an error that should be corrected before its 
  277. // final release. 
  278. if ($post_id = @wp_insert_post($post)) { 
  279. $new_entity = $this->object->find($post_id, TRUE); 
  280. if ($new_entity) { 
  281. foreach ($new_entity->get_entity() as $key => $value) { 
  282. $entity->{$key} = $value; 
  283. // Save properties as post meta 
  284. $this->object->_flush_and_update_postmeta($post_id, $entity instanceof stdClass ? $entity : $entity->get_entity()); 
  285. $entity->{$primary_key} = $post_id; 
  286. // Clean cache 
  287. $this->object->_cache = array(); 
  288. $entity->id_field = $primary_key; 
  289. return $post_id; 
  290. /** 
  291. * Determines whether the current statement is SELECT 
  292. * @return boolean 
  293. */ 
  294. function is_select_statement() 
  295. return isset($this->object->_query_args['is_select']) && $this->object->_query_args['is_select']; 
  296. /** 
  297. * Determines whether the current statement is DELETE 
  298. * @return type 
  299. */ 
  300. function is_delete_statement() 
  301. return isset($this->object->_query_args['is_delete']) && $this->object->_query_args['is_delete']; 
  302. /** 
  303. * Starts a new DELETE statement 
  304. */ 
  305. function delete() 
  306. $this->object->select(); 
  307. $this->object->_query_args['is_select'] = FALSE; 
  308. $this->object->_query_args['is_delete'] = TRUE; 
  309. return $this->object; 
  310. /** 
  311. * Runs the query 
  312. * @param string $sql optionally run the specified query 
  313. * @return array 
  314. */ 
  315. function run_query($sql = FALSE, $model = FALSE, $convert_to_entities = TRUE) 
  316. $retval = array(); 
  317. $results = array(); 
  318. // All of our custom fields are stored as post meta, but is also stored as a serialized 
  319. // value in the post_content field. Because of this, we don't need to look up and cache the 
  320. // post meta values 
  321. $this->object->_query_args['update_post_meta_cache'] = FALSE; 
  322. $this->object->_query_args['update_post_meta_cache'] = FALSE; 
  323. $this->object->_query_args['no_found_posts'] = FALSE; 
  324. // Don't cache any manual SQL query 
  325. if ($sql) { 
  326. $this->object->_query_args['cache_results'] = FALSE; 
  327. $this->object->_query_args['custom_sql'] = $sql; 
  328. // If this is a select query, then try fetching the results from cache 
  329. $cache_key = md5(json_encode($this->object->_query_args)); 
  330. if ($this->is_select_statement() && $this->object->_use_cache) { 
  331. $results = $this->object->get_from_cache($cache_key); 
  332. // Execute the query 
  333. if (!$results) { 
  334. $query = new WP_Query(array('datamapper' => TRUE)); 
  335. if (isset($this->object->debug)) { 
  336. $this->object->_query_args['debug'] = TRUE; 
  337. $query->query_vars = $this->object->_query_args; 
  338. add_action('pre_get_posts', array(&$this, 'set_query_args'), PHP_INT_MAX - 1, 1); 
  339. $results = $query->get_posts(); 
  340. // Cache the result 
  341. if ($this->is_select_statement()) { 
  342. $this->object->cache($cache_key, $results); 
  343. remove_action('pre_get_posts', array(&$this, 'set_query_args'), PHP_INT_MAX - 1, 1); 
  344. // Convert the result 
  345. if ($convert_to_entities) { 
  346. foreach ($results as $row) { 
  347. $retval[] = $this->object->convert_post_to_entity($row, $model); 
  348. } else { 
  349. $retval = $results; 
  350. // Ensure that we return an empty array when there are no results 
  351. if (!$retval) { 
  352. $retval = array(); 
  353. return $retval; 
  354. /** 
  355. * Ensure that the query args are set. We need to do this in case a third-party 
  356. * plugin overrides our query 
  357. * @param $query 
  358. */ 
  359. function set_query_args($query) 
  360. if ($query->get('datamapper')) { 
  361. $query->query_vars = $this->object->_query_args; 
  362. $filter = isset($query->query_vars['suppress_filters']) ? $query->query_vars['suppress_filters'] : FALSE; 
  363. $query->query_vars['suppress_filters'] = apply_filters('wpml_suppress_filters', $filter); 
  364. /** 
  365. * Fetches the last row 
  366. * @param array $conditions 
  367. * @return C_DataMapper_Entity 
  368. */ 
  369. function find_last($conditions = array(), $model = FALSE) 
  370. $retval = NULL; 
  371. // Get row number for the last row 
  372. $table_name = $this->object->_clean_column($this->object->get_table_name()); 
  373. $object_name = $this->object->_clean_column($this->object->get_object_name()); 
  374. $sql = $this->_wpdb()->prepare("SELECT COUNT(*) FROM {$table_name} WHERE post_type = %s", $object_name); 
  375. $count = $this->_wpdb()->get_var($sql); 
  376. $offset = $count - 1; 
  377. $this->select(); 
  378. if ($conditions) { 
  379. $this->where_and($conditions); 
  380. if ($offset) { 
  381. $this->limit(1, $offset); 
  382. $results = $this->run_query(); 
  383. if ($results) { 
  384. $retval = $model ? $this->object->convert_to_model($results[0]) : $results[0]; 
  385. return $retval; 
  386. /** 
  387. * Returns the number of total records/entities that exist 
  388. * @return int 
  389. */ 
  390. function count() 
  391. $this->object->select($this->object->get_primary_key_column()); 
  392. $retval = $this->object->run_query(FALSE, FALSE, FALSE); 
  393. return count($retval); 
  394. /** 
  395. * Returns the title of the post. Used when post_title is not set 
  396. * @param stdClass $entity 
  397. * @return string 
  398. */ 
  399. function get_post_title($entity) 
  400. return "Untitled {$this->object->get_object_name()}"; 
  401. /** 
  402. * Returns the excerpt of the post. Used when post_excerpt is not set 
  403. * @param stdClass $entity 
  404. * @return string 
  405. */ 
  406. function get_post_excerpt($entity) 
  407. return '';