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