PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/publication_base/application/models/ModelAbstract.php

https://bitbucket.org/Dal-Papa/is-340-publish-base
PHP | 508 lines | 158 code | 45 blank | 305 comment | 21 complexity | fb186cfe1504a2c44571ab2039977e68 MD5 | raw file
  1. <?php
  2. /**
  3. * Application Models
  4. *
  5. * @package Application_Model
  6. * @subpackage Model
  7. * @author Florent De Neve
  8. * @copyright
  9. * @license http://framework.zend.com/license/new-bsd New BSD License
  10. */
  11. /**
  12. * Abstract class that is extended by all base models
  13. *
  14. * @package Application_Model
  15. * @subpackage Model
  16. * @author Florent De Neve
  17. */
  18. abstract class Application_Model_ModelAbstract
  19. {
  20. /**
  21. * Mapper associated with this model instance
  22. *
  23. * @var Application_Model_ModelAbstract
  24. */
  25. protected $_mapper;
  26. /**
  27. * Associative array of columns for this model
  28. *
  29. * @var array
  30. */
  31. protected $_columnsList;
  32. /**
  33. * Associative array of parent relationships for this model
  34. *
  35. * @var array
  36. */
  37. protected $_parentList;
  38. /**
  39. * Associative array of dependent relationships for this model
  40. *
  41. * @var array
  42. */
  43. protected $_dependentList;
  44. /**
  45. * Initializes common functionality in Model classes
  46. */
  47. protected function init()
  48. {
  49. }
  50. /**
  51. * Set the list of columns associated with this model
  52. *
  53. * @param array $data
  54. * @return Application_Model_ModelAbstract
  55. */
  56. public function setColumnsList($data)
  57. {
  58. $this->_columnsList = $data;
  59. return $this;
  60. }
  61. /**
  62. * Returns columns list array
  63. *
  64. * @return array
  65. */
  66. public function getColumnsList()
  67. {
  68. return $this->_columnsList;
  69. }
  70. /**
  71. * Set the list of relationships associated with this model
  72. *
  73. * @param array $data
  74. * @return Application_Model_ModelAbstract
  75. */
  76. public function setParentList($data)
  77. {
  78. $this->_parentList = $data;
  79. return $this;
  80. }
  81. /**
  82. * Returns relationship list array
  83. *
  84. * @return array
  85. */
  86. public function getParentList()
  87. {
  88. return $this->_parentList;
  89. }
  90. /**
  91. * Set the list of relationships associated with this model
  92. *
  93. * @param array $data
  94. * @return Application_Model_ModelAbstract
  95. */
  96. public function setDependentList($data)
  97. {
  98. $this->_dependentList = $data;
  99. return $this;
  100. }
  101. /**
  102. * Returns relationship list array
  103. *
  104. * @return array
  105. */
  106. public function getDependentList()
  107. {
  108. return $this->_dependentList;
  109. }
  110. /**
  111. * Returns the mapper associated with this model
  112. *
  113. * @return Application_Model_Mapper_MapperAbstract
  114. */
  115. public abstract function getMapper();
  116. /**
  117. * Converts database column name to php setter/getter function name
  118. * @param string $column
  119. */
  120. public function columnNameToVar($column)
  121. {
  122. if (! isset($this->_columnsList[$column])) {
  123. throw new Exception("column '$column' not found!");
  124. }
  125. return $this->_columnsList[$column];
  126. }
  127. /**
  128. * Converts database column name to PHP setter/getter function name
  129. * @param string $column
  130. */
  131. public function varNameToColumn($thevar)
  132. {
  133. foreach ($this->_columnsList as $column => $var) {
  134. if ($var == $thevar) {
  135. return $column;
  136. }
  137. }
  138. return null;
  139. }
  140. /**
  141. * Recognize methods for Belongs-To cases:
  142. * <code>findBy&lt;field&gt;()</code>
  143. * <code>findOneBy&lt;field&gt;()</code>
  144. * <code>load&lt;relationship&gt;()</code>
  145. *
  146. * @param string $method
  147. * @throws Exception if method does not exist
  148. * @param array $args
  149. */
  150. public function __call($method, array $args)
  151. {
  152. $matches = array();
  153. $result = null;
  154. if (preg_match('/^find(One)?By(\w+)?$/', $method, $matches)) {
  155. $methods = get_class_methods($this);
  156. $check = 'set' . $matches[2];
  157. $fieldName = $this->varNameToColumn($matches[2]);
  158. if (! in_array($check, $methods)) {
  159. throw new Exception(
  160. "Invalid field {$matches[2]} requested for table"
  161. );
  162. }
  163. if ($matches[1] != '') {
  164. $result = $this->getMapper()->findOneByField($fieldName, $args[0],
  165. $this);
  166. } else {
  167. $result = $this->getMapper()->findByField($fieldName, $args[0],
  168. $this);
  169. }
  170. return $result;
  171. } elseif (preg_match('/load(\w+)/', $method, $matches)) {
  172. $result = $this->getMapper()->loadRelated($matches[1], $this);
  173. return $result;
  174. } elseif (preg_match('/^fetchList/', $method, $matches)) {
  175. return $this->getMapper()->$matches[0]($args[0]);
  176. }
  177. throw new Exception("Unrecognized method '$method()'");
  178. }
  179. /**
  180. * __set() is run when writing data to inaccessible properties overloading
  181. * it to support setting columns.
  182. *
  183. * Example:
  184. * <code>class->column_name='foo'</code> or <code>class->ColumnName='foo'</code>
  185. * will execute the function <code>class->setColumnName('foo')</code>
  186. *
  187. * @param string $name
  188. * @param mixed $value
  189. * @throws Exception if the property/column does not exist
  190. */
  191. public function __set($name, $value)
  192. {
  193. $name = $this->columnNameToVar($name);
  194. $method = 'set' . ucfirst($name);
  195. if (('mapper' == $name) || ! method_exists($this, $method)) {
  196. throw new Exception("name:$name value:$value - Invalid property");
  197. }
  198. $this->$method($value);
  199. }
  200. /**
  201. * __get() is utilized for reading data from inaccessible properties
  202. * overloading it to support getting columns value.
  203. *
  204. * Example:
  205. * <code>$foo=class->column_name</code> or <code>$foo=class->ColumnName</code>
  206. * will execute the function <code>$foo=class->getColumnName()</code>
  207. *
  208. * @param string $name
  209. * @param mixed $value
  210. * @throws Exception if the property/column does not exist
  211. * @return mixed
  212. */
  213. public function __get($name)
  214. {
  215. $method = 'get' . ucfirst($name);
  216. if (('mapper' == $name) || ! method_exists($this, $method)) {
  217. $name = $this->columnNameToVar($name);
  218. $method = 'get' . ucfirst($name);
  219. if (('mapper' == $name) || ! method_exists($this, $method)) {
  220. throw new Exception("name:$name - Invalid property");
  221. }
  222. }
  223. return $this->$method();
  224. }
  225. /**
  226. * Array of options/values to be set for this model. Options without a
  227. * matching method are ignored.
  228. *
  229. * @param array $options
  230. * @return Application_Model_ModelAbstract
  231. */
  232. public function setOptions(array $options)
  233. {
  234. $methods = get_class_methods($this);
  235. foreach ($options as $key => $value) {
  236. $key = preg_replace_callback('/_(.)/',
  237. function ($matches) {
  238. return ucfirst($matches[1]);},
  239. $key);
  240. $method = 'set' . ucfirst($key);
  241. if (in_array($method, $methods)) {
  242. $this->$method($value);
  243. }
  244. }
  245. return $this;
  246. }
  247. /**
  248. * Returns the primary key column name
  249. *
  250. * @see Application_Model_DbTable_TableAbstract::getPrimaryKeyName()
  251. * @return string|array The name or array of names which form the primary key
  252. */
  253. public function getPrimaryKeyName()
  254. {
  255. return $this->getMapper()->getDbTable()->getPrimaryKeyName();
  256. }
  257. /**
  258. * Returns an associative array of column-value pairings if the primary key
  259. * is an array of values, or the value of the primary key if not
  260. *
  261. * @return any|array
  262. */
  263. public function getPrimaryKey()
  264. {
  265. $primary_key = $this->getPrimaryKeyName();
  266. if (is_array($primary_key)) {
  267. $result = array();
  268. foreach ($primary_key as $key) {
  269. $result[$key] = $this->$key;
  270. }
  271. return $result;
  272. } else {
  273. return $this->$primary_key;
  274. }
  275. }
  276. /**
  277. * Finds row by primary key
  278. *
  279. * @param string|array $primary_key
  280. * @return Application_Model_ModelAbstract
  281. *
  282. */
  283. public function find($primary_key)
  284. {
  285. $this->getMapper()->find($primary_key, $this);
  286. return $this;
  287. }
  288. /**
  289. * Returns an array, keys are the field names.
  290. *
  291. * @see Application_Model_Mapper_MapperAbstract::toArray()
  292. * @return array
  293. */
  294. public function toArray()
  295. {
  296. return $this->getMapper()->toArray($this);
  297. }
  298. /**
  299. * Sets the mapper class
  300. *
  301. * @param Application_Model_Mapper_MapperAbstract $mapper
  302. * @return Application_Model_ModelAbstract
  303. */
  304. public function setMapper($mapper)
  305. {
  306. $this->_mapper = $mapper;
  307. return $this;
  308. }
  309. /**
  310. * Saves current loaded row
  311. *
  312. * $ignoreEmptyValues by default is true.
  313. * This option will not update columns with empty values or
  314. * will insert NULL values if inserting
  315. *
  316. * @see Application_Model_Mapper_MapperAbstract::save()
  317. * @param boolean $ignoreEmptyValues
  318. * @param boolean recursive
  319. * @return boolean If the save was sucessful
  320. */
  321. public function save($ignoreEmptyValues = true, $recursive = false, $useTransaction = true)
  322. {
  323. return $this->getMapper()->save($this, $ignoreEmptyValues, $recursive, $useTransaction);
  324. }
  325. /**
  326. * Returns the name of the table that this model represents
  327. *
  328. * @return string
  329. */
  330. public function getTableName() {
  331. return $this->getMapper()->getDbTable()->getTableName();
  332. }
  333. /**
  334. * Compare 2 objects and returns the values that differ
  335. *
  336. * @param Application_Model_ModelAbstract $model Object to be compared to
  337. * @param boolean $ignorePrimaryKey If primary keys should be considered
  338. * @param boolean $relations If should recurse into dependencies and parents
  339. * @param boolean $load If relations should be loaded if they are not already
  340. * @return array The values that differ between the two objects, or is in the
  341. * first that is not in the other
  342. */
  343. /* public function diff(Application_Model_ModelAbstract $model,
  344. $ignorePrimaryKey = true, $relations = false, $load = true
  345. ) {
  346. $other_values = $model->toArray();
  347. if ($ignorePrimaryKey) {
  348. $other_pk = $model->getPrimaryKeyName();
  349. if (is_array($other_pk)) {
  350. foreach ($other_pk as $key) {
  351. unset($other_values[$key]);
  352. }
  353. } else {
  354. unset($other_values[$other_pk]);
  355. }
  356. }
  357. $values = $this->toArray();
  358. if ($ignorePrimaryKey) {
  359. $pk = $this->getPrimaryKeyName();
  360. if (is_array($pk)) {
  361. foreach ($pk as $key) {
  362. unset($values[$key]);
  363. }
  364. } else {
  365. unset($values[$pk]);
  366. }
  367. }
  368. $result = array_diff_assoc($values, $other_values);
  369. if ($relations) {
  370. $all_relations = array_merge($this->getDependentList(), $this->getParentList());
  371. foreach($all_relations as $key => $property) {
  372. $method = 'get' . ucfirst($property);
  373. $value = $this->$method($load);
  374. if (is_null($value)) {
  375. continue;
  376. } elseif ($value instanceof Application_Model_ModelAbstract) {
  377. $pk = $value->getPrimaryKeyName();
  378. $value = $value->toArray();
  379. if ($ignorePrimaryKey) {
  380. if (is_array($pk)) {
  381. foreach ($pk as $key) {
  382. unset($value[$key]);
  383. }
  384. } else {
  385. unset($value[$pk]);
  386. }
  387. }
  388. } elseif (is_array($value)) {
  389. $array = array();
  390. foreach ($value as $val) {
  391. if ($val instanceof Application_Model_ModelAbstract) {
  392. $pk = $val->getPrimaryKeyName();
  393. $val = $val->toArray();
  394. if ($ignorePrimaryKey) {
  395. if (is_array($pk)) {
  396. foreach ($pk as $key) {
  397. unset($val[$key]);
  398. }
  399. } else {
  400. unset($val[$pk]);
  401. }
  402. }
  403. $array[] = $val;
  404. }
  405. }
  406. $value = $array;
  407. }
  408. if (method_exists($model, $method)) {
  409. $other_value = $model->$method($load);
  410. if (is_null($other_value)) {
  411. $other_value = array();
  412. } elseif ($other_value instanceof Application_Model_ModelAbstract) {
  413. $pk = $other_value->getPrimaryKeyName();
  414. $other_value = $other_value->toArray();
  415. if ($ignorePrimaryKey) {
  416. if (is_array($pk)) {
  417. foreach ($pk as $key) {
  418. unset($other_value[$key]);
  419. }
  420. } else {
  421. unset($value[$pk]);
  422. }
  423. }
  424. } elseif (is_array($other_value)) {
  425. $other_array = array();
  426. foreach ($other_value as $val) {
  427. if ($val instanceof Application_Model_ModelAbstract) {
  428. $pk = $val->getPrimaryKeyName();
  429. $val = $val->toArray();
  430. if ($ignorePrimaryKey) {
  431. if (is_array($pk)) {
  432. foreach ($pk as $key) {
  433. unset($val[$key]);
  434. }
  435. } else {
  436. unset($val[$pk]);
  437. }
  438. }
  439. $other_array[] = $val;
  440. }
  441. }
  442. $other_value = $other_array;
  443. }
  444. } else {
  445. $other_value = array();
  446. }
  447. $diff = array_diff_assoc($value, $other_value);
  448. if (! empty($diff)) {
  449. $result[$property] = $diff;
  450. }
  451. }
  452. }
  453. return $result;
  454. }
  455. */
  456. }