PageRenderTime 62ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/inc/patForms/Element/Group.php

https://github.com/chregu/fluxcms
PHP | 657 lines | 362 code | 52 blank | 243 comment | 44 complexity | 847279f30c57a889c963047f9086dad3 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Group element that can be used as a container for elements.
  4. *
  5. * $Id$
  6. *
  7. * @package patForms
  8. * @subpackage patForms_Element
  9. */
  10. /**
  11. * Group element that can be used as a container for elements.
  12. *
  13. * $Id$
  14. *
  15. * @access public
  16. * @package patForms
  17. * @subpackage patForms_Element
  18. * @author Stephan Schmidt <schst@php-tools.net>
  19. * @version 1.0
  20. * @license LGPL
  21. * @todo finish element
  22. */
  23. class patForms_Element_Group extends patForms_Element
  24. {
  25. /**
  26. * Stores the name of the element - this is used mainly by the patForms
  27. * error management and should be set in every element class.
  28. * @access public
  29. */
  30. var $elementName = 'Group';
  31. /**
  32. * The radio element uses a renderer to serialize its content, so we set the flag
  33. * to true here
  34. *
  35. * @access private
  36. * @var array
  37. */
  38. var $usesRenderer = true;
  39. /**
  40. * set here which attributes you want to include in the element if you want to use
  41. * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically
  42. * convert the values from your element definition into element attributes.
  43. *
  44. * @access protected
  45. * @see patForms_Element::convertDefinition2Attribute()
  46. */
  47. var $attributeDefinition = array(
  48. 'id' => array(
  49. 'required' => false,
  50. 'format' => 'string',
  51. 'outputFormats' => array( 'html' ),
  52. ),
  53. 'name' => array(
  54. 'required' => true,
  55. 'format' => 'string',
  56. 'outputFormats' => array( 'html' ),
  57. 'modifiers' => array( 'insertSpecials' => array() ),
  58. ),
  59. 'title' => array(
  60. 'required' => false,
  61. 'format' => 'string',
  62. 'outputFormats' => array( 'html' ),
  63. 'modifiers' => array( 'insertSpecials' => array() ),
  64. ),
  65. 'description' => array(
  66. 'required' => false,
  67. 'format' => 'string',
  68. 'outputFormats' => array(),
  69. 'modifiers' => array( 'insertSpecials' => array() ),
  70. ),
  71. 'label' => array(
  72. 'required' => false,
  73. 'format' => 'string',
  74. 'outputFormats' => array(),
  75. ),
  76. 'display' => array(
  77. 'required' => false,
  78. 'format' => 'string',
  79. 'default' => 'yes',
  80. 'outputFormats' => array(),
  81. ),
  82. 'edit' => array(
  83. 'required' => false,
  84. 'format' => 'string',
  85. 'default' => 'yes',
  86. 'outputFormats' => array(),
  87. ),
  88. 'style' => array(
  89. 'required' => false,
  90. 'outputFormats' => array( 'html' ),
  91. 'format' => 'string',
  92. ),
  93. 'class' => array(
  94. 'required' => false,
  95. 'outputFormats' => array( 'html' ),
  96. 'format' => 'string',
  97. ),
  98. 'position' => array(
  99. 'required' => false,
  100. 'format' => 'int',
  101. 'outputFormats' => array(),
  102. ),
  103. 'disabled' => array(
  104. 'required' => false,
  105. 'format' => 'string',
  106. 'default' => 'no',
  107. 'outputFormats' => array( 'html' )
  108. )
  109. );
  110. /**
  111. * stores the element objects of this form.
  112. * @access protected
  113. * @see addElement()
  114. */
  115. var $elements = array();
  116. /**
  117. * stores a renderer
  118. * @access protected
  119. * @see setRenderer()
  120. */
  121. var $renderer = null;
  122. /**
  123. * define error codes an messages for each form element
  124. *
  125. * @access private
  126. * @var array $validatorErrorCodes
  127. */
  128. var $validatorErrorCodes = array(
  129. "C" => array(
  130. ),
  131. "de" => array(
  132. )
  133. );
  134. /**
  135. * stores the current element count for this form, used to generate the ids for each element
  136. * @access protected
  137. * @see getElementId()
  138. */
  139. var $elementCounter = 0;
  140. /**
  141. * sets the locale (language) to use for the validation error messages of the form.
  142. *
  143. * @access public
  144. * @param string $lang
  145. * @return bool $result True on success
  146. * @see $locale
  147. */
  148. function setLocale( $lang )
  149. {
  150. $this->locale = $lang;
  151. $cnt = count($this->elements);
  152. for ($i = 0; $i < $cnt; $i++) {
  153. $this->elements[$i]->setLocale($lang);
  154. }
  155. return true;
  156. }
  157. /**
  158. * sets the format of the element - this defines which method will be called in your
  159. * element class, along with the {@link mode} property.
  160. *
  161. * @access public
  162. * @param string $format The name of the format you have implemented in your element(s). Default is 'html'
  163. * @see setFormat()
  164. * @see format
  165. * @see serialize()
  166. */
  167. function setFormat( $format )
  168. {
  169. $this->format = strtolower( $format );
  170. $cnt = count($this->elements);
  171. for ($i = 0; $i < $cnt; $i++) {
  172. $this->elements[$i]->setFormat($format);
  173. }
  174. }
  175. /**
  176. * sets the mode of the element that defines which methods will be called in your
  177. * element class, along with the {@link format} property.
  178. *
  179. * @access public
  180. * @param string $mode The mode to set the element to: default|readonly or any other mode you have implemented in your element class(es). Default is 'default'.
  181. * @see setFormat()
  182. * @see mode
  183. * @see serialize()
  184. */
  185. function setMode( $mode )
  186. {
  187. $this->mode = strtolower( $mode );
  188. $cnt = count($this->elements);
  189. for ($i = 0; $i < $cnt; $i++) {
  190. $this->elements[$i]->setMode($mode);
  191. }
  192. }
  193. /**
  194. * sets a renderer object that will be used to render
  195. * the form.
  196. *
  197. * @access public
  198. * @param object renderer object
  199. * @see renderForm()
  200. */
  201. function setRenderer( &$renderer )
  202. {
  203. if( !is_object( $renderer ) ) {
  204. return patErrorManager::raiseError(
  205. PATFORMS_ERROR_INVALID_RENDERER,
  206. "No patForms_Renderer object supplied"
  207. );
  208. }
  209. $this->renderer = &$renderer;
  210. }
  211. /**
  212. * adds an observer to the element
  213. *
  214. * @access public
  215. * @param object patForms_Observer observer
  216. * @return boolean currently always true
  217. */
  218. function attachObserver( &$observer )
  219. {
  220. $this->observers[] = &$observer;
  221. $cnt = count($this->elements);
  222. for ($i = 0; $i < $cnt; $i++) {
  223. $this->elements[$i]->attachObserver($observer);
  224. }
  225. return true;
  226. }
  227. /**
  228. * adds an element to the form - has to be a patForms_Element object. Use the {@link createElement()}
  229. * method to create a new element object. Also takes care of passing on the form's configuration
  230. * including the mode, format and submitted flags to the element.
  231. *
  232. * @access public
  233. * @param object &$element The patForms_Element object to add to this form.
  234. * @return bool $success True if everythng went well, false otherwise.
  235. * @see patForms_Element
  236. * @see createElement()
  237. */
  238. function addElement( &$element )
  239. {
  240. if( !is_object( $element ) ) {
  241. return patErrorManager::raiseError(
  242. PATFORMS_ERROR_ELEMENT_IS_NO_OBJECT,
  243. "Given element is not an object"
  244. );
  245. }
  246. if( patErrorManager::isError( $element ) ) {
  247. return patErrorManager::raiseError(
  248. PATFORMS_ERROR_UNEXPECTED_ERROR,
  249. "Unexpected Error Object!"
  250. );
  251. }
  252. if (!$element->getId()) {
  253. $element->setId( $this->getElementId() );
  254. }
  255. $element->setMode( $this->getMode() );
  256. $element->setFormat( $this->getFormat() );
  257. $element->setSubmitted( $this->getSubmitted() );
  258. array_push( $this->elements, &$element );
  259. return true;
  260. }
  261. /**
  262. * retreives a new element id, used to give each added element a unique id for this
  263. * form (id can be overwritten by setting the id attribute specifically).
  264. *
  265. * @access private
  266. * @return int $elementId The new element id.
  267. */
  268. function getElementId()
  269. {
  270. $this->elementCounter++;
  271. return "pfo" . $this->getName() . $this->elementCounter;
  272. }
  273. /**
  274. * element creation method for the 'HTML' format in the 'default' form mode.
  275. *
  276. * @access public
  277. * @param mixed value of the element
  278. * @return mixed $element The element, or false if failed.
  279. */
  280. function serializeHtmlDefault( $value )
  281. {
  282. // manage display attribute. If set, only the needed hidden
  283. // elements for the subelements will be created.
  284. if( $this->attributes['display'] == 'no' )
  285. {
  286. return $this->createDisplaylessTag( $value );
  287. }
  288. if( $this->renderer === null )
  289. {
  290. return patErrorManager::raiseError(
  291. PATFORMS_ERROR_NO_RENDERER_SET,
  292. "No renderer has been set."
  293. );
  294. }
  295. // edit attribute is inherited by all subelements
  296. if( $this->attributes['edit'] == 'no' )
  297. {
  298. $cnt = count( $this->elements );
  299. for( $i=0; $i < $cnt; $i++ )
  300. {
  301. $this->elements[$i]->setAttribute( 'edit', 'no' );
  302. }
  303. }
  304. return $this->renderer->render( $this );
  305. }
  306. /**
  307. * rewritten for the speciality of the group - creates a collection
  308. * of hidden elements for all subelements of the group.
  309. *
  310. * @access public
  311. * @param mixed value of the element
  312. * @return string $value The element's value
  313. */
  314. function createDisplaylessTag( $value )
  315. {
  316. $this->getAttributesFor( $this->getFormat() );
  317. $tag = '';
  318. $cnt = count( $this->elements );
  319. for( $i=0; $i < $cnt; $i++ )
  320. {
  321. $this->elements[$i]->setAttribute( 'display', 'no' );
  322. $tag .= $this->elements[$i]->serialize();
  323. }
  324. return $tag;
  325. }
  326. /**
  327. * element creation method for the 'HTML' format in the 'readonly' form mode.
  328. * Very simple; just returns the stored element value.
  329. *
  330. * @access public
  331. * @param mixed value of the element
  332. * @return string $value The element's value
  333. */
  334. function serializeHtmlReadonly( $value )
  335. {
  336. // manage display attribute.
  337. if( $this->attributes['display'] == 'no' )
  338. {
  339. return $this->createDisplaylessTag( $value );
  340. }
  341. return $this->renderer->render( $this );
  342. }
  343. /**
  344. * validates the element.
  345. *
  346. * @access public
  347. * @param mixed value of the element
  348. * @return bool $isValid True if element could be validated, false otherwise.
  349. */
  350. function validateElement( $value )
  351. {
  352. $valid = true;
  353. $cnt = count( $this->elements );
  354. for( $i = 0; $i < $cnt; ++$i ) {
  355. if( !$this->elements[$i]->validate() ) {
  356. $valid = false;
  357. }
  358. }
  359. if( $valid == false ) {
  360. return false;
  361. }
  362. return true;
  363. }
  364. /**
  365. * Get an element by its name.
  366. *
  367. * @access public
  368. * @param string $name name of the element
  369. * @return mixed either a patForms element or an array containing patForms elements
  370. * @see getElementById()
  371. */
  372. function &getElementByName( $name )
  373. {
  374. if( $name == '__form' ) {
  375. return $this;
  376. }
  377. $elements = array();
  378. $cnt = count( $this->elements );
  379. for ($i = 0; $i < $cnt; $i++) {
  380. if ($this->elements[$i]->getName() == $name) {
  381. $elements[] = &$this->elements[$i];
  382. continue;
  383. }
  384. if (method_exists($this->elements[$i], 'getElementById')) {
  385. patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
  386. $result = &$this->elements[$i]->getElementByName($name);
  387. patErrorManager::popExpect();
  388. if (!patErrorManager::isError($result)) {
  389. if (is_array($result)) {
  390. $cnt2 = count( $result );
  391. for ($j = 0; $j < $cnt2; $j++) {
  392. $elements[] = &$result[$j];
  393. }
  394. } else {
  395. $elements[] = &$result;
  396. }
  397. }
  398. }
  399. }
  400. switch( count( $elements ) )
  401. {
  402. case 0:
  403. return patErrorManager::raiseError(
  404. PATFORMS_ERROR_ELEMENT_NOT_FOUND,
  405. 'Element '.$name.' could not be found.'
  406. );
  407. break;
  408. case 1:
  409. return $elements[0];
  410. break;
  411. default:
  412. return $elements;
  413. break;
  414. }
  415. }
  416. /**
  417. * Get an element by its id.
  418. *
  419. * @access public
  420. * @param string $id id of the element
  421. * @return object patForms element
  422. */
  423. function &getElementById( $id )
  424. {
  425. $cnt = count( $this->elements );
  426. for( $i = 0; $i < $cnt; $i++ )
  427. {
  428. if( $this->elements[$i]->getId() == $id ) {
  429. return $this->elements[$i];
  430. }
  431. if (method_exists($this->elements[$i], 'getElementById')) {
  432. patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
  433. $result = &$this->elements[$i]->getElementById($id);
  434. patErrorManager::popExpect();
  435. if (!patErrorManager::isError($result)) {
  436. return $result;
  437. }
  438. }
  439. }
  440. return patErrorManager::raiseError(
  441. PATFORMS_ERROR_ELEMENT_NOT_FOUND,
  442. 'Element '.$name.' could not be found.'
  443. );
  444. }
  445. /**
  446. * Get all elements of the group
  447. *
  448. * @access public
  449. * @return array all elements of the group
  450. */
  451. function &getElements()
  452. {
  453. return $this->elements;
  454. }
  455. /**
  456. * serialize start of group
  457. *
  458. * @return null
  459. */
  460. function serializeStart()
  461. {
  462. return null;
  463. }
  464. /**
  465. * serialize end of group
  466. *
  467. * @return null
  468. */
  469. function serializeEnd()
  470. {
  471. return null;
  472. }
  473. /**
  474. * getValidationErrors
  475. *
  476. * @access public
  477. * @return array errors that occured during the validation
  478. */
  479. function getValidationErrors()
  480. {
  481. $this->validationErrors = array();
  482. foreach ($this->elements as $element) {
  483. $childErrors = $element->getValidationErrors();
  484. $this->validationErrors = array_merge($this->validationErrors, $childErrors);
  485. }
  486. return parent::getValidationErrors();
  487. }
  488. /**
  489. * sets the current submitted state of the element. Set this to true if you want the element
  490. * to pick up its submitted data.
  491. *
  492. * @access public
  493. * @param bool $state True if it has been submitted, false otherwise (default).
  494. * @see getSubmitted()
  495. * @see $submitted
  496. */
  497. function setSubmitted( $state )
  498. {
  499. $this->submitted = $state;
  500. $cnt = count($this->elements);
  501. for ($i = 0; $i < $cnt; $i++) {
  502. $this->elements[$i]->setSubmitted($state);
  503. }
  504. }
  505. /**
  506. * retrieves the current value of the element. If none is set, will try to retrieve the
  507. * value from submitted form data.
  508. *
  509. * @access public
  510. * @param boolean Determines whether the method is used from an external script
  511. * @return mixed The value, or an empty string if none found.
  512. * @see setValue()
  513. * @see value
  514. * @see resolveValue()
  515. */
  516. function getValue($external = true)
  517. {
  518. $value = array();
  519. $cnt = count($this->elements);
  520. for ($i = 0; $i < $cnt; $i++) {
  521. $elName = $this->elements[$i]->getName();
  522. $elVal = $this->elements[$i]->getValue($external);
  523. $value[$elName] = $elVal;
  524. }
  525. return $value;
  526. }
  527. /**
  528. * sets the value of the element, which will be used to fill the element with. If none is
  529. * set and the element needs a value, it will load it using the {@link resolveValue()} method.
  530. *
  531. * @access public
  532. * @param mixed $value The value to set
  533. * @see $value
  534. * @see resolveValue()
  535. * @see getValue()
  536. */
  537. function setValue($value)
  538. {
  539. patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
  540. foreach ($values as $elName => $value) {
  541. $el = &$this->getElementByName($elName);
  542. if (patErrorManager::isError($el)) {
  543. continue;
  544. }
  545. $el->setValue($value);
  546. }
  547. patErrorManager::popExpect();
  548. return true;
  549. }
  550. /**
  551. * sets the default value of the element, which will be used to fill the element with.
  552. *
  553. * @access public
  554. * @param mixed $value The value to set
  555. * @see $value
  556. * @see resolveValue()
  557. * @see getValue()
  558. */
  559. function setDefaultValue($value)
  560. {
  561. patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
  562. foreach ($values as $elName => $value) {
  563. $el = &$this->getElementByName($elName);
  564. if (patErrorManager::isError($el)) {
  565. continue;
  566. }
  567. $el->setDefaultValue($value);
  568. }
  569. patErrorManager::popExpect();
  570. return true;
  571. }
  572. /**
  573. * replaces an element in the form
  574. *
  575. * @access public
  576. * @param object $element The patForms_Element object to be replaced
  577. * @param object &$replace The element that will replace the old element
  578. * @return bool $success True if everything went well, false otherwise.
  579. * @see patForms_Element
  580. * @see addElement()
  581. */
  582. function replaceElement( $element, &$replace )
  583. {
  584. if (is_object($element)) {
  585. $element = $element->getId();
  586. }
  587. $cnt = count($this->elements);
  588. for ($i = 0; $i < $cnt; $i++) {
  589. if ($this->elements[$i]->getId() !== $element) {
  590. continue;
  591. }
  592. if( !$replace->getId() ) {
  593. $replace->setId( $this->getElementId() );
  594. }
  595. $replace->setMode( $this->getMode() );
  596. $replace->setFormat( $this->getFormat() );
  597. $replace->setSubmitted( $this->isSubmitted() );
  598. $replace->setLocale( $this->getLocale() );
  599. $this->elements[$i] = &$replace;
  600. return true;
  601. }
  602. return false;
  603. }
  604. }
  605. ?>