PageRenderTime 48ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/extensions/directmongosuite/components/EDMSQuery.php

https://bitbucket.org/zadoev/yii-skeleton
PHP | 889 lines | 741 code | 37 blank | 111 comment | 12 complexity | 81a5e8453e5bd9a5199f074395f421a9 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * EDMSQuery.php
  4. *
  5. * A component to simplify the find methods and result handling of the mongoDB
  6. *
  7. *
  8. * PHP version 5.2+
  9. *
  10. * @author Joe Blocher <yii@myticket.at>
  11. * @copyright 2011 myticket it-solutions gmbh
  12. * @license New BSD License
  13. * @category Database
  14. * @package directmongosuite
  15. * @version 0.2.5
  16. * @since 0.1
  17. */
  18. class EDMSQuery
  19. {
  20. const SORT_ASC = 1;
  21. const SORT_DESC = -1;
  22. const CALLAFTER_MONGODBCREATE = 'callAfterMongoDbCreate';
  23. const CALLAFTER_COLLECTIONCREATE = 'callAfterCollectionCreate';
  24. const CALLAFTER_CURSORCREATE = 'callAfterCursorCreate';
  25. const CALLAFTER_COLLECTIONFIND = 'callAfterCollectionFind';
  26. private $_collectionName;
  27. private $_connectionId;
  28. private $_dbName;
  29. private $_callAfterMongoDbCreate;
  30. private $_callAfterCollectionCreate;
  31. private $_callAfterCursorCreate;
  32. private $_callAfterCollectionFind;
  33. private $_callResults;
  34. protected static $_instance;
  35. private $_collection;
  36. private $_cursor;
  37. private $_db;
  38. /**
  39. * Create a EDMSQuery for the specified collection
  40. * Uses the preconfigured connection from EDMSBehavior if dbName, $connectionId is not set
  41. *
  42. * @param string $collectionName
  43. * @param string $dbName
  44. * @param string $connectionId
  45. */
  46. public function __construct($collectionName,$dbName=null,$connectionId=null)
  47. {
  48. $this->_collectionName = $collectionName;
  49. $this->_dbName = $dbName;
  50. $this->_connectionId = $connectionId;
  51. $this->_callResults = array();
  52. }
  53. /**
  54. * EDMSQuery::instance()
  55. *
  56. * @param mixed $collectionName
  57. * @return
  58. */
  59. public static function instance($collectionName)
  60. {
  61. if (!isset(self::$_instance))
  62. self::$_instance = array();
  63. if (!isset(self::$_instance[$collectionName]))
  64. self::$_instance[$collectionName] = new EDMSQuery($collectionName);
  65. return self::$_instance[$collectionName];
  66. }
  67. /**
  68. * Assign the array(method1=>array($arg1,$arg2,...),method2=>array($arg1,$arg2,...) ...)
  69. * called after creating the MongoDb instance
  70. *
  71. * @param array $methods
  72. * @return EDMSQuery
  73. * @since 0.25
  74. */
  75. public function setCallAfterMongoDbCreate($methods)
  76. {
  77. $this->_callAfterMongoDbCreate = $methods;
  78. return $this;
  79. }
  80. /**
  81. * Assign the array(method1=>array($arg1,$arg2,...),method2=>array($arg1,$arg2,...) ...)
  82. * called after creating the MongoCollection instance
  83. *
  84. * @param array $methods
  85. * @return EDMSQuery
  86. * @since 0.25
  87. */
  88. public function setCallAfterCollectionCreate($methods)
  89. {
  90. $this->_callAfterCollectionCreate = $methods;
  91. return $this;
  92. }
  93. /**
  94. * Assign the array(method1=>array($arg1,$arg2,...),method2=>array($arg1,$arg2,...) ...)
  95. * called after calling the MongoCollection->find
  96. *
  97. * @param array $methods
  98. * @return EDMSQuery
  99. * @since 0.25
  100. */
  101. public function setCallAfterCollectionFind($methods)
  102. {
  103. $this->_callAfterCollectionFind = $methods;
  104. return $this;
  105. }
  106. /**
  107. * Assign the array(method1=>array($arg1,$arg2,...),method2=>array($arg1,$arg2,...) ...)
  108. * called after creating the MongoCollection instance
  109. *
  110. * Example: EDMSQuery::instance($collectionName)->setCallAfterCursorCreate(array('limit'=>1,'sort'=>array('weight'=>1,'title'=>-1)))->findArray($criteria,$select);
  111. *
  112. * @param array $methods
  113. * @return EDMSQuery
  114. * @since 0.25
  115. */
  116. public function setCallAfterCursorCreate($methods)
  117. {
  118. $this->_callAfterCursorCreate = $methods;
  119. return $this;
  120. }
  121. /**
  122. * Call the methods of an object
  123. * @param $object
  124. * @param $methods array('methodName'=>array($arg1,$arg2,...))
  125. * @since 0.25
  126. */
  127. protected function callObjectMethods($object,$methods,$resultKey)
  128. {
  129. if(!empty($object) && !empty($methods))
  130. {
  131. $this->_callResults[$resultKey] = array();
  132. foreach ($methods as $method => $args)
  133. {
  134. if(method_exists($object,$method))
  135. $this->_callResults[$resultKey][$method] = call_user_func_array(array($object,$method), array($args));
  136. else
  137. throw new CException('Method not exists');
  138. }
  139. }
  140. }
  141. /**
  142. * Reset the result of the call_user_func_array methods from $this->callObjectMethods
  143. * @since 0.25
  144. */
  145. public function resetCallResults()
  146. {
  147. unset($this->_callResults);
  148. $this->_callResults = array();
  149. }
  150. /**
  151. * Get the results of the call_user_func_array methods from $this->callObjectMethods
  152. *
  153. * @param null $type
  154. * @param null $method
  155. * @return array|null
  156. * @since 0.25
  157. */
  158. public function getCallResults($type=null,$method=null)
  159. {
  160. if(isset($$type))
  161. {
  162. if(isset($this->_callResults[$type]))
  163. {
  164. if(isset($method))
  165. return isset($this->_callResults[$type][$method]) ? $this->_callResults[$type][$method] : null;
  166. else
  167. return $this->_callResults[$type];
  168. }
  169. else return null;
  170. }
  171. return $this->_callResults;
  172. }
  173. /**
  174. * Get an instance of the PHP MongoDB class
  175. *
  176. * @return edmsMongo
  177. */
  178. public function getDb()
  179. {
  180. if (!isset($this->_db))
  181. $this->_db = Yii::app()->edmsMongoDb($this->_dbName,$this->_connectionId);
  182. $this->callObjectMethods($this->_db,$this->_callAfterMongoDbCreate,self::CALLAFTER_MONGODBCREATE);
  183. return $this->_db;
  184. }
  185. /**
  186. * Get an instance of the PHP MongoCollection class
  187. *
  188. * @return edmsMongoCollection
  189. */
  190. public function getCollection()
  191. {
  192. if (!isset($this->_collection))
  193. {
  194. $this->_collection = Yii::app()->edmsMongoCollection($this->_collectionName,$this->_dbName,$this->_connectionId);
  195. $this->callObjectMethods($this->_collection,$this->_callAfterCollectionCreate,self::CALLAFTER_COLLECTIONCREATE);
  196. }
  197. return $this->_collection;
  198. }
  199. /**
  200. * Returns the current cursor generated by the method findCursor
  201. * @return object MongoCursor
  202. * @since 0.25
  203. */
  204. public function getCursor()
  205. {
  206. return $this->_cursor;
  207. }
  208. /**
  209. * Generate the criteria for searching for keywords
  210. * Set the operator AND (default) or OR when there are more keywords in the string
  211. *
  212. * Usage:
  213. * $criteria = EDMSQuery::getWordsSearchCriteria('example for',array('title','subtitle'));
  214. * will return the criteria to search for title or subtitle containing 'example' AND 'for'
  215. *
  216. * @param string $keywords
  217. * @param array $searchAttributes
  218. * @param boolean $orMode
  219. * @return array
  220. */
  221. public static function getWordsSearchCriteria($keywords,$searchAttributes,$orMode = false)
  222. {
  223. $criteria = array();
  224. if (!empty($keywords))
  225. {
  226. // split words
  227. $words = preg_split("/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|" . "[\s,]*'([^']+)'[\s,]*|" . "[\s,]+/",
  228. $keywords, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  229. if (!empty($words))
  230. {
  231. $orArray = array();
  232. if ($orMode) //combine each word as OR
  233. {
  234. foreach ($words as $word)
  235. {
  236. // regex for containing
  237. $regexObj = new MongoRegex('/' . $word . '/i');
  238. foreach ($searchAttributes as $attribute)
  239. $orArray[] = array($attribute => $regexObj);
  240. }
  241. }
  242. else //combine as AND
  243. {
  244. $andArray = array();
  245. foreach ($searchAttributes as $attribute)
  246. {
  247. $andArray = array();
  248. foreach ($words as $word)
  249. {
  250. $regexObj = new MongoRegex('/'.$word.'/i');
  251. $andArray[] = array($attribute => $regexObj);
  252. }
  253. $orArray[] = array('$and'=>$andArray);
  254. }
  255. }
  256. if (!empty($orArray))
  257. $criteria['$or'] = $orArray;
  258. }
  259. }
  260. return $criteria;
  261. }
  262. /**
  263. * Returns an instance of the PHP class MongoCursor after a find operation
  264. * Applies sort and limit to the cursor if the params are not empty
  265. * Uses the preconfigured connection from the EDMSBehavior
  266. *
  267. * @param array $criteria
  268. * @param array $select
  269. * @param array $sort
  270. * @param integer $limit
  271. * @return MongoCursor
  272. */
  273. public function findCursor($criteria=array(),$select=array(),$sort=array(),$limit=null,$skip=null)
  274. {
  275. //always add the '_id'
  276. if (!empty($select) && !in_array('_id',$select))
  277. array_push($select,'_id');
  278. $this->_cursor = $this->getCollection()->find($criteria, $select);
  279. $this->callObjectMethods($this->_collection,$this->_callAfterCollectionFind,self::CALLAFTER_COLLECTIONFIND);
  280. if (!empty($skip) && is_numeric($skip))
  281. $this->_cursor->skip($skip);
  282. if (!empty($limit) && is_numeric($limit))
  283. $this->_cursor->limit($limit);
  284. if (!empty($sort) && is_array($sort))
  285. $this->_cursor->sort($sort);
  286. $this->callObjectMethods($this->_cursor,$this->_callAfterCursorCreate,self::CALLAFTER_CURSORCREATE);
  287. return $this->_cursor;
  288. }
  289. /**
  290. * Returns an array of the result after a find operation
  291. * Applies sort and limit to the cursor if the params are not empty
  292. * Iterates through the result to return an array
  293. *
  294. * Uses the preconfigured connection from the EDMSBehavior
  295. *
  296. * @param array $criteria
  297. * @param array $select
  298. * @param array $sort
  299. * @param integer $limit
  300. * @return array
  301. */
  302. public function findArray($criteria=array(),$select=array(),$sort=array(),$limit=null,$skip=null)
  303. {
  304. $result = array();
  305. $this->_cursor = $this->findCursor($criteria,$select,$sort,$limit,$skip);
  306. if (!empty($this->_cursor) && $this->_cursor->count())
  307. foreach ($this->_cursor as $id => $value)
  308. $result[] = $value;
  309. return $result;
  310. }
  311. /**
  312. * Returns an array of objects after a find operation
  313. * Applies sort and limit to the cursor if the params are not empty
  314. * Iterates through the result to return an array
  315. *
  316. * Uses the preconfigured connection from the EDMSBehavior
  317. *
  318. * @param array $criteria
  319. * @param array $select
  320. * @param array $sort
  321. * @param integer $limit
  322. * @return array
  323. */
  324. public function findObjects($criteria=array(),$select=array(),$sort=array(),$limit=null,$skip=null)
  325. {
  326. $result = array();
  327. $this->_cursor = $this->findCursor($criteria,$select,$sort,$limit,$skip);
  328. if (!empty($this->_cursor) && $this->_cursor->count())
  329. foreach ($this->_cursor as $id => $value)
  330. $result[] = (object)$value;
  331. return $result;
  332. }
  333. /**
  334. * Returns a DataProvider populated by the result after a find operation
  335. * The 'models' are returned as array, not as objects
  336. * @see EDMSDataProvider.php
  337. *
  338. * Uses the preconfigured connection from the EDMSBehavior
  339. *
  340. * @param array $criteria
  341. * @param array $select the attributes to select
  342. * @param array $config the dataProvider config
  343. * @return EDMSDataProvider
  344. */
  345. public function getArrayDataProvider($criteria=array(),$select=array(),$config=array())
  346. {
  347. $this->_cursor = $this->findCursor($criteria,$select);
  348. return new EDMSDataProvider($this->_cursor,$config);
  349. }
  350. /**
  351. * Returns an array of objects of the result after a find operation
  352. * The 'models' are returned as PHP standard objects 'stdClass'
  353. * @see EDMSDataProvider.php
  354. *
  355. * Uses the preconfigured connection from the EDMSBehavior
  356. *
  357. * @param array $criteria
  358. * @param array $select the attributes to select
  359. * @param array $config the dataProvider config
  360. * @return EDMSDataProvider
  361. */
  362. public function getObjectDataProvider($criteria=array(),$select=array(),$config=array())
  363. {
  364. $this->_cursor = $this->findCursor($criteria,$select);
  365. return new EDMSDataProvider($this->_cursor,$config,'stdClass');
  366. }
  367. /**
  368. * Returns an array of objects of the result after a find operation
  369. * The 'models' are returned as objects of the specified modelClassname
  370. * @see EDMSDataProvider.php
  371. *
  372. * Usage for yiimongodbsuite models or CFormModel
  373. *
  374. * Uses the preconfigured connection from the EDMSBehavior
  375. *
  376. * @param string $modelClassname
  377. * @param array $criteria
  378. * @param array $select the attributes to select
  379. * @param array $config the dataProvider config
  380. * @return EDMSDataProvider
  381. */
  382. public function getModelDataProvider($modelClassname,$criteria=array(),$select=array(),$config=array())
  383. {
  384. $this->_cursor = $this->findCursor($criteria,$select);
  385. return new EDMSDataProvider($this->_cursor,$config,$modelClassname);
  386. }
  387. /**
  388. * Uses the preconfigured connection from the EDMSBehavior to find one record
  389. *
  390. * @param arrqay $criteria
  391. * @param array $select
  392. * @return mixed array the record or false
  393. */
  394. public function findOne($criteria,$select=array())
  395. {
  396. //always add the '_id'
  397. if (!empty($select) && !in_array('_id',$select))
  398. array_push($select,'_id');
  399. $this->_cursor = $this->getCollection()->findOne($criteria, $select);
  400. return !empty($this->_cursor) ? $this->_cursor : false;
  401. }
  402. /**
  403. * Execute the collections group method
  404. * @link http://www.php.net/manual/en/mongocollection.group.php
  405. *
  406. * @param mixed $keys
  407. * @param array $initial
  408. * @param string $reduce
  409. * @param array $options
  410. * @return array
  411. */
  412. public function findGroup($keys,$initial,$reduce,$options)
  413. {
  414. $this->_cursor = $this->getCollection()->group($keys,$initial,new MongoCode($reduce),$options);
  415. $items = $this->_cursor['ok'] == 1 ? $this->_cursor['retval'] : null;
  416. return $items;
  417. }
  418. /**
  419. * EDMSQuery::findGroupBy()
  420. * @see http://www.php.net/manual/en/mongocollection.group.php
  421. *
  422. * Tip: get the count of the grouped values by count('_items')
  423. *
  424. * @param array $attributes
  425. * @param array $criteria
  426. * @return array of array(groupedAttributeName=>value,groupedAttributeName=>value, ...array('_items') => [additional selected attributes])
  427. */
  428. public function findGroupBy($attributes,$select=array(),$criteria=array())
  429. {
  430. if (empty($attributes))
  431. return array();
  432. if (is_string($attributes))
  433. $attributes = array($attributes);
  434. else
  435. if (!is_array($attributes))
  436. return array();
  437. $keys = array();
  438. foreach ($attributes as $attribute)
  439. $keys[$attribute] = true;
  440. $jsDetails = array();
  441. //$select = array_merge(array('_id'),$select); //removed v 0.2.5
  442. foreach ($select as $detail)
  443. $jsDetails[]="out['$detail']=obj.$detail";
  444. $jsDetailsStr = implode(';',$jsDetails);
  445. $initial = array('_items' => array());
  446. $reduce = "function (obj, prev) { out=new Object(); $jsDetailsStr; prev._items.push(out);}";
  447. if (!empty($criteria))
  448. $criteria = array(
  449. 'condition' => $criteria,
  450. );
  451. return $this->findGroup($keys,$initial,$reduce,$criteria);
  452. }
  453. /**
  454. * Find and count the specified attribute or the combination of the attributes
  455. *
  456. * @param mixed $attributes string or array
  457. * @param array $criteria
  458. * @param string $countAlias the alias for the count values
  459. * @return array of array(attributeName=>value,attributeName=>value, ... countAlias=>float)
  460. */
  461. public function findCountBy($attributes,$criteria=array(),$countAlias='count')
  462. {
  463. if (empty($attributes))
  464. return array();
  465. if (is_string($attributes))
  466. $attributes = array($attributes);
  467. else
  468. if (!is_array($attributes))
  469. return array();
  470. $keys = array();
  471. foreach ($attributes as $attribute)
  472. $keys[$attribute] = true;
  473. $initial = array($countAlias => 0);
  474. $reduce = "function(doc, prev) { prev.$countAlias += 1 }";
  475. if (!empty($criteria))
  476. $criteria = array(
  477. 'condition' => $criteria,
  478. );
  479. return $this->findGroup($keys,$initial,$reduce,$criteria);
  480. }
  481. /**
  482. * Find items prepared for usage with a dropdown list
  483. *
  484. * @param $values
  485. * @param string $keys
  486. * @param array $criteria
  487. * @param bool $sortByValues
  488. * @param string $keySeparator
  489. * @param string $valueSeparator
  490. * @return array
  491. * @since 0.2.5
  492. */
  493. public function findDropDownItems($values,$keys='_id',$criteria = array(),$sortByValues=true,$keySeparator='__',$valueSeparator=', ')
  494. {
  495. $result = array();
  496. if(is_string($keys))
  497. $keys = array($keys);
  498. if(is_string($values))
  499. $values = array($values);
  500. $items = $this->findGroupBy($keys,$values,$criteria);
  501. if(!empty($items))
  502. {
  503. foreach($items as $item)
  504. {
  505. $keyStr = '';
  506. foreach($keys as $key)
  507. $keyStr .= empty($keyStr) ? $item[$key] : $keySeparator . $item[$key];
  508. $valueStr = '';
  509. $groupedValues = $item['_items'];
  510. foreach($groupedValues as $values)
  511. foreach($values as $key=>$value)
  512. {
  513. $value = trim($value);
  514. if(empty($value))
  515. continue;
  516. $valueStr .= empty($valueStr) ? $value : $valueSeparator . $value;
  517. }
  518. $result[$keyStr] = $valueStr;
  519. }
  520. }
  521. if($sortByValues)
  522. asort($result);
  523. return $result;
  524. }
  525. /**
  526. * Distinct query for a specific attribute in the collection
  527. *
  528. * @param string $attribute
  529. * @param array $criteria additional criteria
  530. * @return array
  531. */
  532. public function findDistinct($attribute, $criteria = array(),$sort = self::SORT_ASC)
  533. {
  534. $command = array('distinct' => $this->_collectionName, 'key' => $attribute);
  535. if (!empty($criteria))
  536. array_push($command, $criteria);
  537. $result = $this->getDb()->command($command);
  538. $items = $result['ok'] == 1 ? $result['values'] : null;
  539. if (isset($sort) && !empty($items))
  540. {
  541. if ($sort === self::SORT_ASC)
  542. sort($items);
  543. else
  544. if ($sort === self::SORT_DESC)
  545. rsort($items);
  546. }
  547. return $items;
  548. }
  549. /**
  550. * Update parts of a record
  551. *
  552. * @link http://www.php.net/manual/en/mongocollection.update.php
  553. * note: per default only the first found record will be updated
  554. * if not multiflag is set
  555. *
  556. * Since v0.2.5 supports multiple modifiers to
  557. *
  558. * @param array $criteria
  559. * @param array $values
  560. * @param mixed $modifier string or array
  561. * @param boolean $multiple
  562. * @return boolean
  563. */
  564. public function atomicUpdate($criteria,$values,$modifier = '$set', $multiple = false,$options=array())
  565. {
  566. if (empty($values) && !is_array($modifier))
  567. return false;
  568. $action = is_array($modifier) ? $modifier : array($modifier => $values);
  569. if ($multiple)
  570. $options = array_merge($options, array('multiple'=>true));
  571. return $this->getCollection()->update($criteria,$action,$options);
  572. }
  573. /**
  574. * Updates all found records with matching criteria with the specified values
  575. *
  576. * @link http://php.net/manual/de/mongocollection.update.php
  577. *
  578. * @param array $criteria
  579. * @param array $values
  580. * @param string $modifier
  581. * @param boolean $multiple
  582. * @return mixed depends on 'safe' option
  583. */
  584. public function update($criteria,$values,$options=array())
  585. {
  586. return $this->atomicUpdate($criteria,$values,'$set',true,$options);
  587. }
  588. /**
  589. * If no document matches $criteria,
  590. * a new document will be created from $criteria and $values
  591. *
  592. * @link http://php.net/manual/de/mongocollection.update.php
  593. *
  594. * @param array $criteria
  595. * @param array $values
  596. * @param array $options
  597. * @return mixed depends on 'safe' option
  598. */
  599. public function upsert($criteria,$values,$options=array())
  600. {
  601. if (empty($values))
  602. return false;
  603. $options = array_merge($options, array('upsert'=>true));
  604. return $this->getCollection()->update($criteria,$values,$options);
  605. }
  606. /**
  607. * @link http://www.php.net/manual/en/mongocollection.insert.php
  608. *
  609. * @param mixed $values
  610. * @param array $options
  611. * @return mixed depends on 'safe' option
  612. */
  613. public function insert($values,$options=array())
  614. {
  615. return $this->getCollection()->insert($values,$options);
  616. }
  617. /**
  618. * @link http://www.php.net/manual/de/mongocollection.remove.php
  619. *
  620. *
  621. * @param array $criteria
  622. * @param boolean $justOne
  623. * @param array $options
  624. * @return mixed depends on 'safe' option
  625. */
  626. public function remove($criteria,$justOne=false,$options=array())
  627. {
  628. $options['justOne'] = $justOne;
  629. return $this->getCollection()->remove($criteria,$options);
  630. }
  631. /**
  632. * Add an item to a array attribute of all records, that matches the criteria
  633. * @see PHP manual MongoCollection::update
  634. * @link http://www.php.net/manual/en/mongocollection.update.php
  635. *
  636. * @param array $criteria
  637. * @param string $attribute
  638. * @param mixed $value
  639. * @param array $options
  640. * @return boolean
  641. */
  642. public function addToSet($criteria,$attribute,$value,$options=array())
  643. {
  644. return $this->atomicUpdate($criteria,array($attribute=>$value),'$addToSet',true,$options);
  645. }
  646. /**
  647. * Remove a item from an array attribute from all records, that matches the criteria
  648. * @see PHP manual MongoCollection::update
  649. * @link http://www.php.net/manual/en/mongocollection.update.php
  650. *
  651. * @param array $criteria
  652. * @param string $attribute
  653. * @param mixed $value
  654. * @param array $options
  655. * @return boolean
  656. */
  657. public function removeFromSet($criteria,$attribute,$values,$options=array())
  658. {
  659. $action = array('$pull' => array(
  660. $attribute => $values,
  661. ));
  662. $options = array_merge(array('multiple'=>true),$options);
  663. return $this->getCollection()->update($criteria,$action,$options);
  664. }
  665. /**
  666. * Ensure one or multiple indexes in the collection at once
  667. * @param mixed $indexes string or array
  668. */
  669. public function ensureIndexes($indexes)
  670. {
  671. if (is_string($indexes))
  672. $indexes = array($indexes);
  673. if (is_array($indexes))
  674. foreach ($indexes as $index)
  675. $this->getCollection()->ensureIndex($index);
  676. }
  677. /**
  678. * Return the public properties of an object as array
  679. *
  680. * @param mixed $model
  681. * @return
  682. */
  683. public static function modelToArray($model)
  684. {
  685. if (method_exists($model,'getAttributes'))
  686. return $model->getAttributes(); //set model attributes with no validation
  687. else
  688. { //assign the values to the public properties
  689. $class=new ReflectionClass(get_class($model));
  690. $attributes = array();
  691. foreach($model->getProperties() as $property)
  692. {
  693. if($property->isPublic() && !$property->isStatic())
  694. {
  695. $key=$property->getName();
  696. $attributes[$key] = $model->$key;
  697. }
  698. }
  699. return $attributes;
  700. }
  701. }
  702. /**
  703. * Assign attributes to the public properties of a object / model
  704. * if $modelProperties is null, the public, non static properties will be
  705. * extracted by using the models ReflectionClass
  706. *
  707. * @param mixed $attributes
  708. * @param mixed $className
  709. * @return
  710. */
  711. public static function arrayToModel($attributes,$className,$modelProperties = null)
  712. {
  713. $model = new $className;
  714. //assign the $modelProperties
  715. if (isset($modelProperties))
  716. {
  717. foreach($modelProperties as $key)
  718. {
  719. if(array_key_exists($key,$attributes))
  720. $model->$key = $attributes[$key];
  721. }
  722. }
  723. else
  724. if (method_exists($model,'setAttributes'))
  725. $model->setAttributes($attributes,false); //set model attributes with no validation
  726. else
  727. //get the public, non static properties of the model
  728. {
  729. $reflectionClass=new ReflectionClass($model);
  730. foreach($reflectionClass->getProperties() as $property)
  731. {
  732. $key=$property->getName();
  733. if($property->isPublic() &&
  734. !$property->isStatic() &&
  735. array_key_exists($key,$attributes))
  736. $model->$key = $attributes[$key];
  737. }
  738. }
  739. return $model;
  740. }
  741. /**
  742. * Add key=>$value to a criteria array
  743. * @static
  744. * @param $key
  745. * @param $value
  746. * @param null $criteria
  747. * since 0.2.5
  748. */
  749. public static function addCriteria($key,$value,&$criteria = null)
  750. {
  751. if(!isset($criteria))
  752. $criteria = array();
  753. $criteria[$key] = $value;
  754. }
  755. }