Mixin_DataMapper_Driver_Base

Provides instance methods for C_DataMapper_Driver_Base.

Defined (1)

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

/products/photocrati_nextgen/modules/datamapper/package.module.datamapper.php  
  1. class Mixin_DataMapper_Driver_Base extends Mixin 
  2. /** 
  3. * Used to clean column or table names in a SQL query 
  4. * @param string $val 
  5. * @return string 
  6. */ 
  7. function _clean_column($val) 
  8. return str_replace(array(';', "'", '"', '`'), array(''), $val); 
  9. /** 
  10. * Notes that a particular columns is serialized, and should be unserialized when converted to an entity 
  11. * @param $column 
  12. */ 
  13. function add_serialized_column($column) 
  14. $this->object->_serialized_columns[] = $column; 
  15. function unserialize_columns($object) 
  16. foreach ($this->object->_serialized_columns as $column) { 
  17. if (isset($object->{$column}) && is_string($object->{$column})) { 
  18. $object->{$column} = $this->unserialize($object->{$column}); 
  19. /** 
  20. * Serializes the data 
  21. * @param mixed $value 
  22. * @return string 
  23. */ 
  24. function serialize($value) 
  25. return M_DataMapper::serialize($value); 
  26. /** 
  27. * Unserializes data using our proprietary format 
  28. * @param string $value 
  29. * @return mixed 
  30. */ 
  31. function unserialize($value) 
  32. return M_DataMapper::unserialize($value); 
  33. /** 
  34. * Finds a partiular entry by id 
  35. * @param int|stdClass|C_DataMapper_Model $entity 
  36. * @return C_DataMapper_Entity 
  37. */ 
  38. function find($entity, $model = FALSE) 
  39. $retval = NULL; 
  40. // Get primary key of the entity 
  41. $pkey = $this->object->get_primary_key_column(); 
  42. if (!is_numeric($entity)) { 
  43. $entity = isset($entity->{$pkey}) ? intval($entity->{$pkey}) : FALSE; 
  44. // If we have an entity ID, then get the record 
  45. if ($entity) { 
  46. $results = $this->object->select()->where_and(array("{$pkey} = %d", $entity))->limit(1, 0)->run_query(); 
  47. if ($results) { 
  48. $retval = $model ? $this->object->convert_to_model($results[0]) : $results[0]; 
  49. return $retval; 
  50. /** 
  51. * Fetches the first row 
  52. * @param array $conditions 
  53. * @return C_DataMapper_Entity 
  54. */ 
  55. function find_first($conditions = array(), $model = FALSE) 
  56. $results = $this->object->select()->where_and($conditions)->limit(1, 0)->run_query(); 
  57. if ($results) { 
  58. return $model ? $this->object->convert_to_model($results[0]) : $results[0]; 
  59. } else { 
  60. return NULL; 
  61. /** 
  62. * Queries all rows 
  63. * @param array $conditions 
  64. * @return array 
  65. */ 
  66. function find_all($conditions = array(), $model = FALSE) 
  67. // Sometimes users will forget that the first parameter is conditions, and think it's $model instead 
  68. if ($conditions === TRUE) { 
  69. $conditions = array(); 
  70. $model = TRUE; 
  71. if ($conditions === FALSE) { 
  72. $conditions = array(); 
  73. $results = $this->object->select()->where_and($conditions)->run_query(); 
  74. if ($results && $model) { 
  75. foreach ($results as &$r) { 
  76. $r = $this->object->convert_to_model($r); 
  77. return $results; 
  78. /** 
  79. * Filters the query using conditions: 
  80. * E.g. 
  81. * array("post_title = %s", "Foo") 
  82. * array( 
  83. * array("post_title = %s", "Foo"),  
  84. * ) 
  85. */ 
  86. function where_and($conditions = array()) 
  87. return $this->object->_where($conditions, 'AND'); 
  88. function where_or($conditions = array()) 
  89. return $this->object->where($conditions, 'OR'); 
  90. function where($conditions = array()) 
  91. return $this->object->_where($conditions, 'AND'); 
  92. /** Parses the where clauses 
  93. * They could look like the following: 
  94. * array( 
  95. * "post_id = 1" 
  96. * array("post_id = %d", 1),  
  97. * ) 
  98. * or simply "post_id = 1" 
  99. * @param array|string $conditions 
  100. * @param string $operator 
  101. * @return ExtensibleObject 
  102. */ 
  103. function _where($conditions = array(), $operator) 
  104. $where_clauses = array(); 
  105. // If conditions is not an array, make it one 
  106. if (!is_array($conditions)) { 
  107. $conditions = array($conditions); 
  108. } elseif (!empty($conditions) && !is_array($conditions[0])) { 
  109. // Just a single condition was passed, but with a bind 
  110. $conditions = array($conditions); 
  111. // Iterate through each condition 
  112. foreach ($conditions as $condition) { 
  113. if (is_string($condition)) { 
  114. $clause = $this->object->_parse_where_clause($condition); 
  115. if ($clause) { 
  116. $where_clauses[] = $clause; 
  117. } else { 
  118. $clause = array_shift($condition); 
  119. $clause = $this->object->_parse_where_clause($clause, $condition); 
  120. if ($clause) { 
  121. $where_clauses[] = $clause; 
  122. // Add where clause to query 
  123. if ($where_clauses) { 
  124. $this->object->_add_where_clause($where_clauses, $operator); 
  125. return $this->object; 
  126. /** 
  127. * Parses a where clause and returns an associative array 
  128. * representing the query 
  129. * E.g. parse_where_clause("post_title = %s", "Foo Bar") 
  130. * @global wpdb $wpdb 
  131. * @param string $condition 
  132. * @return array 
  133. */ 
  134. function _parse_where_clause($condition) 
  135. $column = ''; 
  136. $operator = ''; 
  137. $value = ''; 
  138. $numeric = TRUE; 
  139. // Substitute any placeholders 
  140. global $wpdb; 
  141. $binds = func_get_args(); 
  142. $binds = isset($binds[1]) ? $binds[1] : array(); 
  143. // first argument is the condition 
  144. foreach ($binds as &$bind) { 
  145. // A bind could be an array, used for the 'IN' operator 
  146. // or a simple scalar value. We need to convert arrays 
  147. // into scalar values 
  148. if (is_object($bind)) { 
  149. $bind = (array) $bind; 
  150. if (is_array($bind) && !empty($bind)) { 
  151. foreach ($bind as &$val) { 
  152. if (!is_numeric($val)) { 
  153. $val = '"' . addslashes($val) . '"'; 
  154. $numeric = FALSE; 
  155. $bind = implode(', ', $bind); 
  156. } else { 
  157. if (is_array($bind) && empty($bind)) { 
  158. $bind = 'NULL'; 
  159. } else { 
  160. if (!is_numeric($bind)) { 
  161. $numeric = FALSE; 
  162. if ($binds) { 
  163. $condition = $wpdb->prepare($condition, $binds); 
  164. // Parse the where clause 
  165. if (preg_match("/^[^\\s]+/", $condition, $match)) { 
  166. $column = trim(array_shift($match)); 
  167. $condition = str_replace($column, '', $condition); 
  168. if (preg_match("/(NOT )?IN|(NOT )?LIKE|(NOT )?BETWEEN|[=!<>]+/i", $condition, $match)) { 
  169. $operator = trim(array_shift($match)); 
  170. $condition = str_replace($operator, '', $condition); 
  171. $operator = strtolower($operator); 
  172. $value = trim($condition); 
  173. // Values will automatically be quoted, so remove them 
  174. // If the value is part of an IN clause or BETWEEN clause and 
  175. // has multiple values, we attempt to split the values apart into an 
  176. // array and iterate over them individually 
  177. if ($operator == 'in') { 
  178. $values = preg_split("/'?\\s?(, )\\s?'?/i", $value); 
  179. } elseif ($operator == 'between') { 
  180. $values = preg_split("/'?\\s?(AND)\\s?'?/i", $value); 
  181. // If there's a single value, treat it as an array so that we 
  182. // can still iterate 
  183. if (empty($values)) { 
  184. $values = array($value); 
  185. foreach ($values as $index => $value) { 
  186. $value = preg_replace("/^(\\()?'/", '', $value); 
  187. $value = preg_replace("/'(\\))?\$/", '', $value); 
  188. $values[$index] = $value; 
  189. if (count($values) > 1) { 
  190. $value = $values; 
  191. // Return the WP Query meta query parameters 
  192. $retval = array('column' => $column, 'value' => $value, 'compare' => strtoupper($operator), 'type' => $numeric ? 'numeric' : 'string'); 
  193. return $retval; 
  194. /** 
  195. * Converts a stdObject to an Entity 
  196. * @param stdObject $stdObject 
  197. * @return stdObject 
  198. */ 
  199. function _convert_to_entity($stdObject) 
  200. // Add name of the id_field to the entity, and convert 
  201. // the ID to an integer 
  202. $stdObject->id_field = $key = $this->object->get_primary_key_column(); 
  203. // Cast columns to their appropriate data type 
  204. $this->cast_columns($stdObject); 
  205. // Strip slashes 
  206. $this->strip_slashes($stdObject); 
  207. // Unserialize columns 
  208. $this->unserialize_columns($stdObject); 
  209. // Set defaults for this entity 
  210. if (!$this->has_default_values($stdObject)) { 
  211. $this->object->set_defaults($stdObject); 
  212. $stdObject->__defaults_set = TRUE; 
  213. return $stdObject; 
  214. function strip_slashes($stdObject_or_array_or_string) 
  215. /** 
  216. * Some objects have properties that are recursive objects. To avoid this we have to keep track 
  217. * of what objects we've already processed when we're running this method recursively 
  218. */ 
  219. static $level = 0; 
  220. static $processed_objects = array(); 
  221. $level++; 
  222. $processed_objects[] = $stdObject_or_array_or_string; 
  223. if (is_string($stdObject_or_array_or_string)) { 
  224. $stdObject_or_array_or_string = str_replace("\\'", "'", str_replace('\\"', '"', str_replace("\\\\", "\\", $stdObject_or_array_or_string))); 
  225. } elseif (is_object($stdObject_or_array_or_string) && !in_array($stdObject_or_array_or_string, $processed_objects)) { 
  226. foreach (get_object_vars($stdObject_or_array_or_string) as $key => $val) { 
  227. if ($val != $stdObject_or_array_or_string && $key != '_mapper') { 
  228. $stdObject_or_array_or_string->{$key} = $this->strip_slashes($val); 
  229. $processed_objects[] = $stdObject_or_array_or_string; 
  230. } elseif (is_array($stdObject_or_array_or_string)) { 
  231. foreach ($stdObject_or_array_or_string as $key => $val) { 
  232. if ($key != '_mixins') { 
  233. $stdObject_or_array_or_string[$key] = $this->strip_slashes($val); 
  234. $level--; 
  235. if ($level == 0) { 
  236. $processed_objects = array(); 
  237. return $stdObject_or_array_or_string; 
  238. /** 
  239. * Converts a stdObject entity to a model 
  240. * @param stdObject $stdObject 
  241. */ 
  242. function convert_to_model($stdObject, $context = FALSE) 
  243. // Create a factory 
  244. $retval = NULL; 
  245. try { 
  246. $this->object->_convert_to_entity($stdObject); 
  247. } catch (Exception $ex) { 
  248. throw new E_InvalidEntityException($ex); 
  249. $retval = $this->object->create($stdObject, $context); 
  250. return $retval; 
  251. /** 
  252. * Creates a new model 
  253. * @param stdClass|array $properties 
  254. * @return C_DataMapper_Model 
  255. */ 
  256. function create($properties = array(), $context = FALSE) 
  257. $entity = $properties; 
  258. $factory = C_Component_Factory::get_instance(); 
  259. if (!is_object($properties)) { 
  260. $entity = new stdClass(); 
  261. foreach ($properties as $k => $v) { 
  262. $entity->{$k} = $v; 
  263. return $factory->create($this->object->get_model_factory_method(), $entity, $this->object, $context); 
  264. /** 
  265. * Determines whether an object is actually a model 
  266. * @param mixed $obj 
  267. * @return bool 
  268. */ 
  269. function is_model($obj) 
  270. return is_subclass_of($obj, 'C_DataMapper_Model') or get_class($obj) == 'C_DataMapper_Model'; 
  271. /** 
  272. * Saves an entity 
  273. * @param stdClass|C_DataMapper_Model $entity 
  274. * @return bool 
  275. */ 
  276. function save($entity) 
  277. $retval = FALSE; 
  278. $model = $entity; 
  279. // Attempt to use something else, most likely an associative array 
  280. // TODO: Support assocative arrays. The trick is to support references 
  281. // with dynamic calls using __call() and call_user_func_array(). 
  282. if (is_array($entity)) { 
  283. throw new E_InvalidEntityException(); 
  284. } elseif (!$this->object->is_model($entity)) { 
  285. unset($entity->__defaults_set); 
  286. $model = $this->object->convert_to_model($entity); 
  287. // Validate the model 
  288. $model->validate(); 
  289. if ($model->is_valid()) { 
  290. $saved_entity = $model->get_entity(); 
  291. unset($saved_entity->_errors); 
  292. $retval = $this->object->_save_entity($saved_entity); 
  293. // We always return the same type of entity that we given 
  294. if (get_class($entity) == 'stdClass') { 
  295. $model->get_entity(); 
  296. return $retval; 
  297. /** 
  298. * Gets validation errors for the entity 
  299. * @param stdClass|C_DataMapper_Model $entity 
  300. * @return array 
  301. */ 
  302. function get_errors($entity) 
  303. $model = $entity; 
  304. if (!$this->object->is_model($entity)) { 
  305. $model = $this->object->convert_to_model($entity); 
  306. $model->validate(); 
  307. return $model->get_errors(); 
  308. /** 
  309. * Called to set defaults for the record/model/entity. 
  310. * Subclasses and adapters should extend this method to provide their 
  311. * implementation. The implementation should make use of the 
  312. * _set_default_value() method 
  313. */ 
  314. function set_defaults() 
  315. function has_default_values($entity) 
  316. return isset($entity->__defaults_set) && $entity->__defaults_set == TRUE; 
  317. /** 
  318. * If a field has no value, then use the default value. 
  319. * @param stdClass|C_DataMapper_Model $object 
  320. */ 
  321. function _set_default_value($object) 
  322. $array = NULL; 
  323. $field = NULL; 
  324. $default_value = NULL; 
  325. // The first argument MUST be an object 
  326. if (!is_object($object)) { 
  327. throw new E_InvalidEntityException(); 
  328. // This method has two signatures: 
  329. // 1) _set_default_value($object, $field, $default_value) 
  330. // 2) _set_default_value($object, $array_field, $field, $default_value) 
  331. // Handle #1 
  332. $args = func_get_args(); 
  333. if (count($args) == 4) { 
  334. list($object, $array, $field, $default_value) = $args; 
  335. if (!isset($object->{$array})) { 
  336. $object->{$array} = array(); 
  337. $object->{$array}[$field] = NULL; 
  338. } else { 
  339. $arr =& $object->{$array}; 
  340. if (!isset($arr[$field])) { 
  341. $arr[$field] = NULL; 
  342. $array =& $object->{$array}; 
  343. $value =& $array[$field]; 
  344. if ($value === '' or is_null($value)) { 
  345. $value = $default_value; 
  346. } else { 
  347. list($object, $field, $default_value) = $args; 
  348. if (!isset($object->{$field})) { 
  349. $object->{$field} = NULL; 
  350. $value = $object->{$field}; 
  351. if ($value === '' or is_null($value)) { 
  352. $object->{$field} = $default_value; 
  353. function define_column($name, $type, $default_value = NULL) 
  354. $this->object->_columns[$name] = array('type' => $type, 'default_value' => $default_value); 
  355. function get_defined_column_names() 
  356. return array_keys($this->object->_columns); 
  357. function has_defined_column($name) 
  358. $columns = $this->object->_columns; 
  359. return isset($columns[$name]); 
  360. function cast_columns($entity) 
  361. foreach ($this->object->_columns as $key => $properties) { 
  362. $value = property_exists($entity, $key) ? $entity->{$key} : NULL; 
  363. $default_value = $properties['default_value']; 
  364. if (!is_null($value) && $value !== $default_value) { 
  365. $column_type = $this->object->_columns[$key]['type']; 
  366. if (preg_match("/varchar|text/i", $column_type)) { 
  367. if (!is_array($value) && !is_object($value)) { 
  368. $entity->{$key} = strval($value); 
  369. } else { 
  370. if (preg_match("/decimal|numeric|double|float/i", $column_type)) { 
  371. $entity->{$key} = floatval($value); 
  372. } else { 
  373. if (preg_match("/int/i", $column_type)) { 
  374. $entity->{$key} = intval($value); 
  375. } else { 
  376. if (preg_match("/bool/i", $column_type)) { 
  377. $entity->{$key} = $value ? TRUE : FALSE; 
  378. } else { 
  379. $entity->{$key} = $default_value; 
  380. return $entity;