PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/fuel/packages/orm/classes/observer/validation.php

https://bitbucket.org/codeyash/bootstrap
PHP | 219 lines | 129 code | 25 blank | 65 comment | 14 complexity | 46f40c989943103727c0ad7be6a5b10b MD5 | raw file
Possible License(s): MIT, Apache-2.0
  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP5 framework.
  4. *
  5. * @package Fuel
  6. * @version 1.5
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2013 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Orm;
  13. /**
  14. * Exception to throw when validation failed
  15. */
  16. class ValidationFailed extends \FuelException
  17. {
  18. /**
  19. * @var Fieldset the fieldset causing this exception
  20. */
  21. protected $fieldset;
  22. /**
  23. * Overridden \FuelException construct to add a Fieldset instance into the exception
  24. *
  25. * @param string the error message
  26. * @param int the error code
  27. * @param \Exception any previous exception
  28. * @param \Fieldset the fieldset on which this exception was triggered
  29. */
  30. public function __construct($message = null, $code = 0, \Exception $previous = null, \Fieldset $fieldset = null)
  31. {
  32. parent::__construct($message, $code, $previous);
  33. $this->fieldset = $fieldset;
  34. }
  35. /**
  36. * Gets the Fieldset from this exception
  37. *
  38. * @return Fieldset
  39. */
  40. public function get_fieldset()
  41. {
  42. return $this->fieldset;
  43. }
  44. }
  45. /**
  46. * Observer class to validate the properties of the model before save.
  47. *
  48. * It is also used in Fieldset generation based on a model, to populate the fields
  49. * and field validation rules of the Fieldset.
  50. */
  51. class Observer_Validation extends Observer
  52. {
  53. /**
  54. * Set a Model's properties as fields on a Fieldset, which will be created with the Model's
  55. * classname if none is provided.
  56. *
  57. * @param string
  58. * @param \Fieldset|null
  59. * @return \Fieldset
  60. */
  61. public static function set_fields($obj, $fieldset = null)
  62. {
  63. static $_generated = array();
  64. static $_tabular_rows = array();
  65. $class = is_object($obj) ? get_class($obj) : $obj;
  66. if (is_null($fieldset))
  67. {
  68. $fieldset = \Fieldset::instance($class);
  69. if ( ! $fieldset)
  70. {
  71. $fieldset = \Fieldset::forge($class);
  72. }
  73. }
  74. // is our parent fieldset a tabular form set?
  75. $tabular_form = is_object($fieldset->parent()) ? $fieldset->parent()->get_tabular_form() : false;
  76. // don't cache tabular form fieldsets
  77. if ( ! $tabular_form)
  78. {
  79. ! array_key_exists($class, $_generated) and $_generated[$class] = array();
  80. if (in_array($fieldset, $_generated[$class], true))
  81. {
  82. return $fieldset;
  83. }
  84. $_generated[$class][] = $fieldset;
  85. }
  86. $primary_keys = is_object($obj) ? $obj->primary_key() : $class::primary_key();
  87. $primary_key = count($primary_keys) === 1 ? reset($primary_keys) : false;
  88. $properties = is_object($obj) ? $obj->properties() : $class::properties();
  89. if ($tabular_form and $primary_key and ! is_object($obj))
  90. {
  91. isset($_tabular_rows[$class]) or $_tabular_rows[$class] = 0;
  92. }
  93. foreach ($properties as $p => $settings)
  94. {
  95. if (\Arr::get($settings, 'skip', in_array($p, $primary_keys)))
  96. {
  97. continue;
  98. }
  99. if (isset($settings['form']['options']))
  100. {
  101. foreach ($settings['form']['options'] as $key => $value)
  102. {
  103. is_array($value) or $settings['form']['options'][$key] = \Lang::get($value, array(), false) ?: $value;
  104. }
  105. }
  106. // field attributes can be passed in form key
  107. $attributes = isset($settings['form']) ? $settings['form'] : array();
  108. // label is either set in property setting, as part of form attributes or defaults to fieldname
  109. $label = isset($settings['label']) ? $settings['label'] : (isset($attributes['label']) ? $attributes['label'] : $p);
  110. $label = \Lang::get($label, array(), false) ?: $label;
  111. // change the fieldname and label for tabular form fieldset children
  112. if ($tabular_form and $primary_key)
  113. {
  114. if (is_object($obj))
  115. {
  116. $p = $tabular_form.'['.$obj->{$primary_key}.']['.$p.']';
  117. }
  118. else
  119. {
  120. $p = $tabular_form.'_new['.$_tabular_rows[$class].']['.$p.']';
  121. }
  122. $label = '';
  123. }
  124. // create the field and add validation rules
  125. $field = $fieldset->add($p, $label, $attributes);
  126. if ( ! empty($settings['validation']))
  127. {
  128. foreach ($settings['validation'] as $rule => $args)
  129. {
  130. if (is_int($rule) and is_string($args))
  131. {
  132. $args = array($args);
  133. }
  134. else
  135. {
  136. array_unshift($args, $rule);
  137. }
  138. call_user_func_array(array($field, 'add_rule'), $args);
  139. }
  140. }
  141. }
  142. // increase the row counter for tabular row fieldsets
  143. if ($tabular_form and $primary_key and ! is_object($obj))
  144. {
  145. $_tabular_rows[$class]++;
  146. }
  147. return $fieldset;
  148. }
  149. /**
  150. * Execute before saving the Model
  151. *
  152. * @param Model the model object to validate
  153. *
  154. * @throws ValidationFailed
  155. */
  156. public function before_save(Model $obj)
  157. {
  158. $this->validate($obj);
  159. }
  160. /**
  161. * Validate the model
  162. *
  163. * @param Model the model object to validate
  164. *
  165. * @throws ValidationFailed
  166. */
  167. public function validate(Model $obj)
  168. {
  169. $fieldset = static::set_fields($obj);
  170. $val = $fieldset->validation();
  171. // only allow partial validation on updates, specify the fields for updates to allow null
  172. $allow_partial = $obj->is_new() ? false : array();
  173. $input = array();
  174. foreach (array_keys($obj->properties()) as $p)
  175. {
  176. if ( ! in_array($p, $obj->primary_key()) and $obj->is_changed($p))
  177. {
  178. $input[$p] = $obj->{$p};
  179. is_array($allow_partial) and $allow_partial[] = $p;
  180. }
  181. }
  182. if ( ! empty($input) and $val->run($input, $allow_partial, array($obj)) === false)
  183. {
  184. throw new ValidationFailed($val->show_errors(), 0, null, $fieldset);
  185. }
  186. else
  187. {
  188. foreach ($input as $k => $v)
  189. {
  190. $obj->{$k} = $val->validated($k);
  191. }
  192. }
  193. }
  194. }