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

/app/protected/extensions/zurmoinc/framework/forms/ModelForm.php

https://bitbucket.org/zurmo/zurmo/
PHP | 283 lines | 175 code | 21 blank | 87 comment | 19 complexity | 0fc7c64946cf8658063a08cafc86d33e MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-3.0, LGPL-2.1, BSD-2-Clause
  1. <?php
  2. /*********************************************************************************
  3. * Zurmo is a customer relationship management program developed by
  4. * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
  5. *
  6. * Zurmo is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU General Public License version 3 as published by the
  8. * Free Software Foundation with the addition of the following permission added
  9. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  10. * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
  11. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  12. *
  13. * Zurmo is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU General Public License along with
  19. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  20. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21. * 02110-1301 USA.
  22. *
  23. * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
  24. * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
  25. ********************************************************************************/
  26. /**
  27. * Provides an interface that is the same as a RedBeanModel
  28. * interface, but allows developer to extend RedBeanModel
  29. * with additional attributes that are not part of the model.
  30. */
  31. abstract class ModelForm extends CModel
  32. {
  33. private static $_names = array();
  34. protected $model;
  35. public function __construct(RedBeanModel $model)
  36. {
  37. $this->model = $model;
  38. }
  39. public function getModel()
  40. {
  41. return $this->model;
  42. }
  43. public function __toString()
  44. {
  45. return strval($this->model);
  46. }
  47. public function __set($name, $value)
  48. {
  49. if (property_exists($this, $name))
  50. {
  51. $this->$name = $value;
  52. }
  53. else
  54. {
  55. $this->model->$name = $value;
  56. }
  57. }
  58. public function __get($name)
  59. {
  60. if (property_exists($this, $name))
  61. {
  62. return $this->$name;
  63. }
  64. return $this->model->$name;
  65. }
  66. /**
  67. * Interface to mimic model getMetadata method.
  68. * Can only be called non-statically since the model is required.
  69. */
  70. public function getMetadata()
  71. {
  72. return $this->model->getMetadata();
  73. }
  74. /**
  75. * If the attribute exists on the form, then assume it is not a relation since the form
  76. * does not support relational attributes.
  77. */
  78. public function isRelation($attributeName)
  79. {
  80. if (property_exists($this, $attributeName))
  81. {
  82. return false;
  83. }
  84. return $this->model->isRelation($attributeName);
  85. }
  86. /**
  87. * If the attribute exists on the form, then assume it is not a relation since the form
  88. * does not support relational attributes.
  89. */
  90. public function getRelationModelClassName($relationName)
  91. {
  92. if (property_exists($this, $relationName))
  93. {
  94. return false;
  95. }
  96. return $this->model->getRelationModelClassName($relationName);
  97. }
  98. /**
  99. * Returns true if the named attribute is a property on this
  100. * model.
  101. */
  102. public function isAttribute($attributeName)
  103. {
  104. assert('is_string($attributeName)');
  105. assert('$attributeName != ""');
  106. if (property_exists($this, $attributeName))
  107. {
  108. return true;
  109. }
  110. return $this->model->isAttribute($attributeName);
  111. }
  112. /**
  113. * Override to properly check if the attribute is required or not.
  114. * (non-PHPdoc)
  115. * @see CModel::isAttributeRequired()
  116. */
  117. public function isAttributeRequired($attribute)
  118. {
  119. if (property_exists($this, $attribute))
  120. {
  121. return parent::isAttributeRequired($attribute);
  122. }
  123. return $this->model->isAttributeRequired($attribute);
  124. }
  125. /**
  126. * Returns the list of attribute names.
  127. * By default, this method returns all public properties of the class.
  128. * You may override this method to change the default.
  129. * @return array list of attribute names. Defaults to all public properties of the class.
  130. */
  131. public function attributeNames()
  132. {
  133. $className = get_class($this);
  134. if (!isset(self::$_names[$className]))
  135. {
  136. $class = new ReflectionClass(get_class($this));
  137. $names = array();
  138. foreach ($class->getProperties() as $property)
  139. {
  140. $name = $property->getName();
  141. if ($property->isPublic() && !$property->isStatic())
  142. {
  143. $names[] = $name;
  144. }
  145. }
  146. return self::$_names[$className] = $names;
  147. }
  148. else
  149. {
  150. return self::$_names[$className];
  151. }
  152. }
  153. public function getAttributeLabel($attribute)
  154. {
  155. assert('is_string($attribute)');
  156. assert('$attribute != ""');
  157. $attributeLabels = $this->attributeLabels();
  158. if (isset($attributeLabels[$attribute]))
  159. {
  160. return $attributeLabels[$attribute];
  161. }
  162. return $this->model->getAttributeLabel($attribute);
  163. }
  164. /**
  165. * Override of setAttributes in CModel to support setting attributes into this form as well
  166. * as the related model. Splits $values into two arrays. First array is name/value pairs of attributes
  167. * on this form, whereas the second array is name/value pairs on the model.
  168. */
  169. public function setAttributes($values, $safeOnly = true)
  170. {
  171. $formValues = array();
  172. $modelValues = array();
  173. foreach ($values as $name => $value)
  174. {
  175. if (property_exists($this, $name))
  176. {
  177. $formValues[$name] = $value;
  178. }
  179. else
  180. {
  181. $modelValues[$name] = $value;
  182. }
  183. }
  184. parent::setAttributes($formValues, $safeOnly);
  185. $this->model->setAttributes($modelValues, $safeOnly);
  186. }
  187. /**
  188. * Performs validation on this form and the model.
  189. * clearErrors is not supported, because the model does not support this
  190. * parameter in the RedBeanModel->validate() function.
  191. * Currently this method does not support specifying the $attributes parameter.
  192. */
  193. public function validate($attributes = null, $clearErrors = true)
  194. {
  195. assert('$clearErrors == true');
  196. assert('$attributes == null');
  197. $formValidatedSuccessfully = parent::validate($attributes);
  198. $modelValidatedSuccessfully = $this->model->validate($attributes, static::shouldIgnoreRequiredValidator());
  199. if (!$modelValidatedSuccessfully || !$formValidatedSuccessfully)
  200. {
  201. return false;
  202. }
  203. return true;
  204. }
  205. /**
  206. * Override to properly get validators for an attribute when they are on the model.
  207. * Todo: Factor in scenario for model attributes.
  208. * (non-PHPdoc)
  209. * @see CModel::getValidators()
  210. */
  211. public function getValidators($attribute = null)
  212. {
  213. if ($attribute != null && !property_exists($this, $attribute))
  214. {
  215. return $this->model->getValidators($attribute);
  216. }
  217. return parent::getValidators($attribute);
  218. }
  219. /**
  220. * Override and set to true if you need to ignore the required validator.
  221. */
  222. protected static function shouldIgnoreRequiredValidator()
  223. {
  224. return false;
  225. }
  226. /**
  227. * Return array of errors on form and model.
  228. * Currently this method does not support specifying the $attributeNameOrNames parameter.
  229. */
  230. public function getErrors($attributeNameOrNames = null)
  231. {
  232. $formErrors = parent::getErrors($attributeNameOrNames);
  233. $modelErrors = $this->model->getErrors($attributeNameOrNames);
  234. return array_merge($formErrors, $modelErrors);
  235. }
  236. /**
  237. * @return true/false. If the form and/or the model has any errors.
  238. * Currently this method does not support specifying the $attributeNameOrNames parameter.
  239. */
  240. public function hasErrors($attributeNameOrNames = null)
  241. {
  242. $hasFormErrors = parent::hasErrors($attributeNameOrNames);
  243. if ($hasFormErrors)
  244. {
  245. return true;
  246. }
  247. return false;
  248. }
  249. /**
  250. * Saves the model.
  251. */
  252. public function save($runValidation = true, array $attributeNames = null)
  253. {
  254. assert('$attributeNames == null');
  255. if (!$runValidation || $this->validate())
  256. {
  257. return $this->model->save($runValidation);
  258. }
  259. return false;
  260. }
  261. }
  262. ?>