PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Nano/library/Nano/Form/Element/Abstract.php

http://mvh-source.googlecode.com/
PHP | 289 lines | 185 code | 55 blank | 49 comment | 28 complexity | 5a2eefeb63a4b1d20eaf9a88ac2c3478 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. <?php
  2. abstract class Nano_Form_Element_Abstract extends Nano_Element{
  3. protected $decorator = 'Nano_Form_Decorator_Input';
  4. protected $_label;
  5. protected $_type = 'input';
  6. protected $_validators;
  7. protected $_wrapper;
  8. protected $_required;
  9. protected $_prefix;
  10. protected $_suffix;
  11. protected $_errors = array();
  12. public function __construct( $name, $attributes ){
  13. $defaults = array(
  14. 'label' => null,
  15. 'required' => false,
  16. 'validators' => array(),
  17. 'validator' => null,
  18. 'prefix' => null,
  19. 'suffix' => null,
  20. 'elements' => null,
  21. 'wrapper' => new Nano_Element( 'div', array('class' => 'formElementWrapper')),
  22. );
  23. $config = array_filter(array_merge( $defaults, array_intersect_key( $attributes, $defaults )));
  24. $attributes = array_diff_key( $attributes, $config );
  25. $attributes['name'] = $name;
  26. foreach( $config as $key => $value ){
  27. if( ( $method = 'add' . ucfirst( $key ) ) && method_exists( $this, $method ) ){
  28. $this->$method( $value );
  29. }
  30. else if( ( $property = '_' . $key ) && property_exists( $this, $property ) ){
  31. $this->$property = $value;
  32. }
  33. }
  34. parent::__construct( $this->_type, $attributes );
  35. }
  36. /**
  37. * Add a child element. This function can act as a factory, by supplying
  38. * constructor arguments for Nano_Element. If the first argument is an instance
  39. * of Nano_Element, the element is appended as is
  40. *
  41. * @param mixed $args Mixed, may be a Nano_Element or the element type,
  42. * @param string $attributes If $args is not a Nano_Element, optional attributes
  43. * @param string $content If $args not Nano_Element, content of the element
  44. * @return Nano_Form_Element $this
  45. */
  46. public function addChild( $args ){
  47. $children = $this->getChildren();
  48. $args = func_get_args();
  49. $element = array_shift( $args );
  50. if( ! $element instanceof Nano_Element ){
  51. $attributes = array_shift( $args );
  52. $content = array_shift( $args );
  53. $element = new Nano_Element( $element, $attributes, $content );
  54. }
  55. $children[] = $element;
  56. return $this;
  57. }
  58. /**
  59. * Add a form element. This method is different from add child,
  60. * since it takes in account that the element is one of the Form_
  61. * family, and may default to Input
  62. *
  63. * @param $name Name of the attribute. This MUST be set and will be used
  64. * as the name attribute. It therefore MUST be unique to this form.
  65. *
  66. * @param $attributes Will be passed immediately to the new element
  67. * @return Nano_Form_Element The newly created element
  68. */
  69. public function addElement( $name, $attributes = array() ){
  70. if( count($attributes) == 0 ) return true;
  71. $klass = 'Nano_Form_Element_Input';
  72. //if( $attributes instanceof Nano_Element ){
  73. // $this->addChild( $attributes );
  74. // return $attributes
  75. //}
  76. if( $name instanceof Nano_Element ){
  77. $this->addChild( $name );
  78. return $name;
  79. }
  80. if( isset( $attributes['type'] ) ){
  81. $k = sprintf('Nano_Form_Element_%s', ucfirst($attributes['type']));
  82. if( class_exists( $k ) ){// input/type can be a separate class.
  83. $klass = $k;
  84. }
  85. }
  86. $element = new $klass( $name, $attributes );
  87. $this->addChild( $element );
  88. return $element;
  89. }
  90. /**
  91. * Add multipe elements in one go. $elements is expected to contain
  92. * a valid array of paramaters for addElement or it will throw an Exception
  93. *
  94. * @param array $elements Array with elements array($type=>'type', $name=>'nane',$value,$attr)
  95. * @return Nano_Form $this
  96. */
  97. public function addElements( array $elements ){
  98. foreach( $elements as $name => $arguments ){
  99. $this->addElement( $name, $arguments );
  100. }
  101. }
  102. /**
  103. * Return default arguments - use this to set up some defaults
  104. */
  105. protected function getDefaultAttributes(){
  106. return array();
  107. }
  108. public function addValidators( $validators ){
  109. foreach( $validators as $validator ){
  110. @list( $method, $options, $breakOnFaillure ) = $validator;
  111. $this->addValidator( $method, $options, $breakOnFaillure );
  112. }
  113. return $this;
  114. }
  115. public function addValidator( $method, $options, $breakOnFaillure = false ){
  116. if( null === $this->_validators ){
  117. $this->_validators = array();
  118. }
  119. $className = sprintf('Nano_Form_Validator_%s', ucfirst($method));
  120. if( class_exists( $className ) ){
  121. $validator = new $className( $options, $breakOnFaillure );
  122. }
  123. else{
  124. //if( function_exists( $className ) ){
  125. $validator = new Nano_Form_Validator_Function( $method, $options, $breakOnFaillure );
  126. }
  127. $this->_validators[] = $validator;
  128. }
  129. /**
  130. * Validates the form
  131. *
  132. * @param mixed $post Post array. will be cast to array
  133. * @return bool $has_errors Wether the element has errors.
  134. */
  135. public function validate( $post ){
  136. $childErrors = array();
  137. $this->_errors = array();
  138. foreach( $this->getChildren() as $child ){
  139. if( $child instanceof Nano_Form_Element_Abstract ){
  140. $childErrors = array_merge( $childErrors, $child->validate( $post ));
  141. }
  142. }
  143. if( is_array( $this->_validators ) && count( $this->_validators ) > 0 ){
  144. $key = $this->getAttribute('name');
  145. $values = (array) $post;
  146. $value = key_exists( $key, $values ) ? $values[$key] : null;
  147. foreach( $this->_validators as $validator ){
  148. $return = $validator->validate( $value );
  149. if( true !== $return ){
  150. $this->setError( $key, $return );
  151. }
  152. }
  153. }
  154. $this->_errors = array_merge( $childErrors, $this->getErrors() );
  155. if( count( $this->_errors ) > 0 ){
  156. $this->setAttribute( 'class', trim($this->getAttribute('class') . ' error'));
  157. }
  158. return $this->_errors;
  159. //return (bool) count($this->_errors);
  160. }
  161. /**
  162. * Check if form is valid. This function will return FALSE if the form
  163. * has not yet been validated!
  164. *
  165. * @return boolean $valid
  166. */
  167. public function isValid(){
  168. return !( (bool) count($this->_errors) );
  169. }
  170. public function setError( $name, $message ){
  171. if( null == $this->_errors ){
  172. $this->_errors = array();
  173. }
  174. if( ! key_exists( $name, $this->_errors ) ){
  175. $this->_errors[$name] = array();
  176. }
  177. $this->_errors[$name][] = $message;
  178. }
  179. public function hasErrors(){
  180. return (bool) count( $this->_errors );
  181. }
  182. public function getErrors(){
  183. if( null == $this->_errors ){
  184. $this->_errors = array();
  185. }
  186. return $this->_errors;
  187. }
  188. private function getValidators(){
  189. if( null == $this->validators ){
  190. $this->validators = new Nano_Collection();
  191. }
  192. return $this->validators;
  193. }
  194. public function getValue(){
  195. return $this->getAttribute( 'value' );
  196. }
  197. public function setValue( $value ){
  198. $this->setAttribute( 'value', $value );
  199. return $this;
  200. }
  201. public function setLabel( $label ){
  202. $this->_label = $label;
  203. return $this;
  204. }
  205. public function getLabel(){
  206. return $this->_label;
  207. }
  208. public function setWrapper( $wrapper ){
  209. if( $wrapper instanceof Nano_Element ){
  210. $this->_wrapper = $wrapper;
  211. }
  212. else if( null !== $wrapper ){
  213. $this->_wrapper = false;
  214. }
  215. }
  216. public function getWrapper(){
  217. return $this->_wrapper;
  218. }
  219. public function setPrefix( $value ){
  220. $this->_prefix = $value;
  221. }
  222. public function getPrefix(){
  223. return $this->_prefix;
  224. }
  225. public function setSuffix( $value ){
  226. $this->_suffix = $value;
  227. }
  228. public function getSuffix(){
  229. return $this->_suffix;
  230. }
  231. public function setRequired( $required = true ){
  232. $this->_required = true;
  233. }
  234. }