PageRenderTime 68ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/inc/patForms.php

https://github.com/chregu/fluxcms
PHP | 2819 lines | 1530 code | 301 blank | 988 comment | 211 complexity | cb9862037ff4832c2e8b6578c1e06cc5 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * patForms form manager class - serialize form elements into any given output format
  4. * using element classes, and build the output via renderer classes.
  5. *
  6. * $Id$
  7. *
  8. * @package patForms
  9. * @author Sebastian Mordziol <argh@php-tools.net>
  10. * @author gERD Schaufelberger <gerd@php-tools.net>
  11. * @author Stephan Schmidt <schst@php-tools.net>
  12. * @copyright 2003-2004 PHP Application Tools
  13. * @license LGPL
  14. * @link http://www.php-tools.net
  15. */
  16. /**
  17. * set the include path
  18. */
  19. if( !defined( 'PATFORMS_INCLUDE_PATH' ) ) {
  20. define( 'PATFORMS_INCLUDE_PATH', dirname( __FILE__ ). '/patForms' );
  21. }
  22. /**
  23. * location of global javascripts
  24. */
  25. define('PATFORMS_SCRIPT_PATH', PATFORMS_INCLUDE_PATH . '/Scripts');
  26. /**
  27. * needs helper methods of patForms_Element
  28. */
  29. include_once PATFORMS_INCLUDE_PATH . "/Element.php";
  30. /**
  31. * error definition: renderer base class file (renderers/_base.php) could not
  32. * be found.
  33. *
  34. * @see patForms::_createModule()
  35. */
  36. define( "PATFORMS_ERROR_NO_MODULE_BASE_FILE", 1001 );
  37. /**
  38. * error definition: the specified renderer could not be found.
  39. *
  40. * @see patForms::_createModule()
  41. */
  42. define( "PATFORMS_ERROR_MODULE_NOT_FOUND", 1002 );
  43. /**
  44. * error definition: the element added via the {@link patForms::addElement()}
  45. * is not an object. Use the {@link patForms::createElement()} method to
  46. * create an element object.
  47. *
  48. * @see patForms::addElement()
  49. * @see patForms::createElement()
  50. */
  51. define( "PATFORMS_ERROR_ELEMENT_IS_NO_OBJECT", 1003 );
  52. /**
  53. * error definition: generic unexpected error.
  54. */
  55. define( "PATFORMS_ERROR_UNEXPECTED_ERROR", 1004 );
  56. /**
  57. * element does not exist
  58. */
  59. define( "PATFORMS_ERROR_ELEMENT_NOT_FOUND", 1012 );
  60. /**
  61. * renderer object has not been set - if you want to render the form, you have to
  62. * set a renderer object via the {@link patForms::setRenderer()} method. To create
  63. * a renderer, use the {@link patForms::createRenderer()} method.
  64. *
  65. * @see patForms::setRenderer()
  66. * @see patForms::createRenderer()
  67. */
  68. define( "PATFORMS_ERROR_NO_RENDERER_SET", 1013 );
  69. /**
  70. * invalid renderer
  71. *
  72. * @see createRenderer()
  73. */
  74. define( "PATFORMS_ERROR_INVALID_RENDERER", 1014 );
  75. /**
  76. * invalid method
  77. *
  78. * @see setMethod()
  79. */
  80. define( "PATFORMS_ERROR_INVALID_METHOD", 1015 );
  81. /**
  82. * Given parameter is not a boolean value
  83. */
  84. define( "PATFORMS_ERROR_PARAMETER_NO_BOOL", 1016 );
  85. /**
  86. * Given Static property does not exist
  87. */
  88. define( "PATFORMS_ERROR_NO_STATIC_PROPERTY", 1017 );
  89. /**
  90. * Unknown event
  91. */
  92. define( "PATFORMS_ERROR_UNKNOWN_EVENT", 1018 );
  93. /**
  94. * Invalid event handler
  95. */
  96. define( "PATFORMS_ERROR_INVALID_HANDLER", 1019 );
  97. /**
  98. * Event exists
  99. */
  100. define( 'PATFORMS_NOTICE_EVENT_ALREADY_REGISTERED', 1020 );
  101. /**
  102. * Invalid storage container
  103. */
  104. define( 'PATFORMS_ERROR_INVALID_STORAGE', 1021 );
  105. define( 'PATFORMS_NOTICE_ARRAY_EXPECTED', 1022 );
  106. define( 'PATFORMS_NOTICE_ATTRIBUTE_NOT_SUPPORTED', 1023 );
  107. define( 'PATFORMS_NOTICE_INVALID_OPTION', 1024 );
  108. define( 'PATFORMS_ERROR_ATTRIBUTE_REQUIRED', 1025 );
  109. define( 'PATFORMS_ERROR_CAN_NOT_VERIFY_FORMAT', 1026 );
  110. define( 'PATFORMS_ERROR_METHOD_FOR_MODE_NOT_AVAILABLE', 1027 );
  111. /**
  112. * errors apply on translating errors matching current locale settings
  113. */
  114. define( 'PATFORMS_NOTICE_VALIDATOR_ERROR_LOCALE_UNDEFINED', 1028 );
  115. define( 'PATFORMS_WARNING_VALIDATOR_ERROR_UNDEFINED', 1029 );
  116. /**
  117. * Script file could not be loaded
  118. */
  119. define( 'PATFORMS_WARNING_SCRIPTFILE_NOT_FOUND', 1040 );
  120. /**
  121. * apply the rule before the built-in validation
  122. */
  123. define( 'PATFORMS_RULE_BEFORE_VALIDATION', 1 );
  124. /**
  125. * apply the rule after the built-in validation
  126. */
  127. define( 'PATFORMS_RULE_AFTER_VALIDATION', 2 );
  128. /**
  129. * apply the rule before AND after the built-in validation
  130. */
  131. define( 'PATFORMS_RULE_BOTH', 3 );
  132. /**
  133. * attach the observer to the elements
  134. */
  135. define( 'PATFORMS_OBSERVER_ATTACH_TO_ELEMENTS', 1 );
  136. /**
  137. * attach the observer to the form
  138. */
  139. define( 'PATFORMS_OBSERVER_ATTACH_TO_FORM', 2 );
  140. /**
  141. * attach the observer to the form and the elements
  142. */
  143. define( 'PATFORMS_OBSERVER_ATTACH_TO_BOTH', 3 );
  144. /**
  145. * group values should stay nested
  146. */
  147. define('PATFORMS_VALUES_NESTED', 0);
  148. /**
  149. * group values should be flattened
  150. */
  151. define('PATFORMS_VALUES_FLATTENED', 1);
  152. /**
  153. * group values should be prefixed
  154. */
  155. define('PATFORMS_VALUES_PREFIXED', 2);
  156. /**
  157. * Static patForms properties - used to emulate pre-PHP5 static properties.
  158. *
  159. * @see setStaticProperty()
  160. * @see getStaticProperty()
  161. */
  162. $GLOBALS['_patForms'] = array(
  163. 'format' => 'html',
  164. 'locale' => 'C',
  165. 'customLocales' => array(),
  166. 'autoFinalize' => true,
  167. 'defaultAttributes' => array(),
  168. 'elementCounter' => 0,
  169. );
  170. /**
  171. * patForms form manager class - serialize form elements into any given output format
  172. * using element classes, and build the output via renderer classes.
  173. *
  174. * @package patForms
  175. * @author Sebastian Mordziol <argh@php-tools.net>
  176. * @author gERD Schaufelberger <gerd@php-tools.net>
  177. * @author Stephan Schmidt <schst@php-tools.net>
  178. * @copyright 2003-2004 PHP Application Tools
  179. * @license LGPL
  180. * @link http://www.php-tools.net
  181. * @version 1.0
  182. * @todo check the clientside functionality, as that can lead to broken pages
  183. */
  184. class patForms
  185. {
  186. /**
  187. * javascript that will displayed only once
  188. *
  189. * @access private
  190. * @var array
  191. */
  192. var $globalJavascript = array();
  193. /**
  194. * javascript that will be displayed once per instance
  195. *
  196. * @access private
  197. * @var array
  198. */
  199. var $instanceJavascript = array();
  200. /**
  201. * stores the mode for the form. It defaults to 'default', and is only overwritten if
  202. * set specifically. It is passed on to any elements you create.
  203. *
  204. * @access private
  205. * @see setMode()
  206. */
  207. var $mode = 'default';
  208. /**
  209. * XML entities
  210. *
  211. * @access private
  212. * @see toXML()
  213. * @todo This is redundant to the Element's xmlEntities property - find a way to keep this in one place
  214. */
  215. var $xmlEntities = array(
  216. "<" => "&lt;",
  217. ">" => "&gt;",
  218. "&" => "&amp;",
  219. "'" => "&apos;",
  220. '"' => "&quot;"
  221. );
  222. /**
  223. * stores the format for the element. It defaults to 'html', and is only overwritten if
  224. * set specifically. It is passed on to any elements you create.
  225. *
  226. * @access private
  227. * @see setFormat()
  228. */
  229. var $format = 'html';
  230. /**
  231. * stores the flag telling the form whether it has been submitted - this is passed on to any
  232. * elements you create.
  233. *
  234. * @access private
  235. * @see setSubmitted()
  236. */
  237. var $submitted = false;
  238. /**
  239. * stores the element objects of this form.
  240. * @access private
  241. * @see addElement()
  242. */
  243. var $elements = array();
  244. /**
  245. * stores a renderer
  246. * @access private
  247. * @see setRenderer(), renderForm()
  248. */
  249. var $renderer = null;
  250. /**
  251. * stores the locale to use when adding validation errors for the whole form.
  252. *
  253. * @access private
  254. * @var string $locale
  255. * @see setLocale()
  256. */
  257. var $locale = 'C';
  258. /**
  259. * stores custom locale
  260. *
  261. * @access private
  262. * @var array
  263. * @see setLocale()
  264. */
  265. var $customLocales = array();
  266. /**
  267. * stores the element name
  268. * @access private
  269. * @see getElementName()
  270. */
  271. var $elementName = 'Form';
  272. /**
  273. * flag to indicate, whether form should be validated automatically
  274. * by renderForm()
  275. *
  276. * @access private
  277. * @var string
  278. * @see setAutoValidate(), renderForm()
  279. */
  280. var $autoValidate = false;
  281. /**
  282. * name of the variable that indicates, whether the form has
  283. * been submitted.
  284. *
  285. * @access private
  286. * @var string
  287. * @see setAutoValidate()
  288. */
  289. var $submitVar = null;
  290. /**
  291. * event handlers
  292. *
  293. * @access private
  294. * @var array
  295. * @see registerEventHandler()
  296. * @see registerEvent()
  297. */
  298. var $_eventHandler = array();
  299. /**
  300. * events that can be triggered
  301. *
  302. * @access private
  303. * @var array
  304. * @see registerEventHandler()
  305. * @see triggerEvent()
  306. * @see registerEvent()
  307. */
  308. var $_validEvents = array( 'onInit', 'onSubmit', 'onError', 'onSuccess' );
  309. /**
  310. * Stores whether the current form has been validated
  311. *
  312. * @access private
  313. */
  314. var $validated = false;
  315. /**
  316. * Stores whether the current form is valid or not (after the
  317. * validation process)
  318. *
  319. * @access private
  320. */
  321. var $valid = null;
  322. /**
  323. * Stores the names of all static properties that patForms will use as defaults
  324. * for the properties with the same name on startup.
  325. *
  326. * @access private
  327. */
  328. var $staticProperties = array(
  329. 'format' => 'setFormat',
  330. 'autoFinalize' => 'setAutoFinalize',
  331. 'locale' => 'setLocale',
  332. );
  333. /**
  334. * Stores the flag for the autoFinalize feature
  335. *
  336. * @access private
  337. */
  338. var $autoFinalize = true;
  339. /**
  340. * custom validation rules
  341. *
  342. * @access private
  343. * @var array
  344. */
  345. var $_rules = array();
  346. /**
  347. * define error codes an messages for the form
  348. *
  349. * Will be set by validation rules that have been
  350. * added to the form.
  351. *
  352. * @access private
  353. * @var array $validatorErrorCodes
  354. */
  355. var $validatorErrorCodes = array();
  356. /**
  357. * stores any validation errors that can occurr during the
  358. * form's validation process.
  359. *
  360. * @access private
  361. * @var array $validationErrors
  362. */
  363. var $validationErrors = array();
  364. /**
  365. * next error offset for rules
  366. * @access private
  367. * @var integer
  368. */
  369. var $nextErrorOffset = 1000;
  370. /**
  371. * Attributes of the form - needed to generate the form tag
  372. *
  373. * @access private
  374. * @var array $attributes
  375. * @see setAttribute()
  376. */
  377. var $attributes = array();
  378. /**
  379. * Attribute definition for the form - defines which attribute the form
  380. * itself supports.
  381. *
  382. * @access public
  383. */
  384. var $attributeDefinition = array(
  385. 'id' => array(
  386. 'required' => false,
  387. 'format' => 'string',
  388. 'outputFormats' => array( 'html' ),
  389. ),
  390. 'name' => array(
  391. 'required' => true,
  392. 'format' => 'string',
  393. 'outputFormats' => array( 'html' ),
  394. ),
  395. 'method' => array(
  396. 'required' => true,
  397. 'format' => 'string',
  398. 'default' => 'post',
  399. 'outputFormats' => array( 'html' ),
  400. ),
  401. 'action' => array(
  402. 'required' => true,
  403. 'format' => 'string',
  404. 'outputFormats' => array( 'html' ),
  405. ),
  406. 'accept' => array(
  407. 'required' => false,
  408. 'format' => 'string',
  409. 'outputFormats' => array( 'html' ),
  410. ),
  411. 'accept-charset' => array(
  412. 'required' => false,
  413. 'format' => 'string',
  414. 'outputFormats' => array( 'html' ),
  415. ),
  416. 'enctype' => array(
  417. 'required' => false,
  418. 'format' => 'string',
  419. 'outputFormats' => array( 'html' ),
  420. ),
  421. 'onreset' => array(
  422. 'required' => false,
  423. 'format' => 'string',
  424. 'outputFormats' => array( 'html' ),
  425. ),
  426. 'onsubmit' => array(
  427. 'required' => false,
  428. 'format' => 'string',
  429. 'outputFormats' => array( 'html' ),
  430. ),
  431. 'target' => array(
  432. 'required' => false,
  433. 'format' => 'string',
  434. 'outputFormats' => array( 'html' ),
  435. ),
  436. );
  437. /**
  438. * Stores all available patForms options - these are inherited by all elements
  439. * and their dependencies, like rules.
  440. *
  441. * Short option overview:
  442. *
  443. * - scripts: enable client script integration
  444. *
  445. * @access public
  446. */
  447. var $options = array(
  448. 'scripts' => array(
  449. 'enabled' => false,
  450. 'params' => array(
  451. 'folder' => PATFORMS_SCRIPT_PATH,
  452. 'jsInclude' => false
  453. ),
  454. ),
  455. );
  456. /**
  457. * observers of the form
  458. *
  459. * @access private
  460. * @var array
  461. */
  462. var $observers = array();
  463. /**
  464. * Sets the default attributes that will be inherited by any elements you add to the form.
  465. *
  466. * <b>Note:</b> You have to call this method statically before creating a new form if you use
  467. * patForm's automatic element creation feature via the {@link createForm()} method, as the
  468. * default attributes cannot be set after an element has been created.
  469. *
  470. * @static
  471. * @access public
  472. * @param array $attributes The list of attributes to set with key => value pairs.
  473. */
  474. function setDefaultAttributes( $attributes )
  475. {
  476. patForms::setStaticProperty( 'defaultAttributes', $attributes );
  477. }
  478. /**
  479. * sets the locale (language) to use for the validation error messages of all elements
  480. * in the form.
  481. *
  482. * @access public
  483. * @param string language code
  484. * @param string optional language file
  485. * @return bool True on success
  486. */
  487. function setLocale( $locale, $languageFile = null )
  488. {
  489. if (!is_null($languageFile)) {
  490. $languageData = patForms::parseLocaleFile($languageFile);
  491. $customLocales = patForms::getStaticProperty('customLocales');
  492. $customLocales[$locale] = $languageData;
  493. patForms::setStaticProperty('customLocales', $customLocales);
  494. }
  495. if( isset( $this ) && is_a( $this, 'patForms' ) ) {
  496. $this->locale = $locale;
  497. if( !empty( $this->elements ) ) {
  498. $cnt = count( $this->elements );
  499. for( $i=0; $i < $cnt; $i++ ) {
  500. $this->elements[$i]->setLocale( $locale );
  501. }
  502. }
  503. } else {
  504. patForms::setStaticProperty('locale', $locale);
  505. }
  506. return true;
  507. }
  508. /**
  509. * checks, whether a locale is a custom locale
  510. *
  511. * @static
  512. * @access public
  513. * @param string locale name
  514. * @return boolean
  515. */
  516. function isCustomLocale($locale)
  517. {
  518. $customLocales = patForms::getStaticProperty('customLocales');
  519. if (isset($customLocales[$locale])) {
  520. return true;
  521. }
  522. return false;
  523. }
  524. /**
  525. * get the custom locale for an element or a rule
  526. *
  527. * @static
  528. * @access public
  529. * @param string locale
  530. * @param string key
  531. * @return array
  532. */
  533. function getCustomLocale($locale, $key)
  534. {
  535. $customLocales = patForms::getStaticProperty('customLocales');
  536. if (!isset($customLocales[$locale])) {
  537. return false;
  538. }
  539. if (!isset($customLocales[$locale][$key])) {
  540. return false;
  541. }
  542. return $customLocales[$locale][$key];
  543. }
  544. /**
  545. * parses a locale file
  546. *
  547. * @access private
  548. * @param string filename
  549. * @return array locale information
  550. * @todo add some file checks
  551. */
  552. function parseLocaleFile($filename)
  553. {
  554. return parse_ini_file($filename, true);
  555. }
  556. /**
  557. * sets the format of the element - this will be passed on to any elements you create. If you
  558. * have already added some elements when you call this method, it will be passed on to them too.
  559. *
  560. * @access public
  561. * @param string $format The name of the format you have implemented in your element(s).
  562. * @return bool $result True on success
  563. * @see setMode()
  564. * @see format
  565. * @see serialize()
  566. */
  567. function setFormat( $format )
  568. {
  569. if( isset( $this ) && is_a( $this, 'patForms' ) )
  570. {
  571. $this->format = strtolower( $format );
  572. if( !empty( $this->elements ) )
  573. {
  574. $cnt = count( $this->elements );
  575. for( $i=0; $i < $cnt; $i++ )
  576. {
  577. $this->elements[$i]->setFormat( $format );
  578. }
  579. }
  580. }
  581. else
  582. {
  583. patForms::setStaticProperty( 'format', $format );
  584. }
  585. return true;
  586. }
  587. /**
  588. * sets the mode of the form - If you have already added some elements when you call this
  589. * method, it will be passed on to them too.
  590. *
  591. * @access public
  592. * @param string $mode The mode to set the form to: default|readonly or any other mode you have implemented in your element class(es). Default is 'default'.
  593. * @see setMode()
  594. * @see mode
  595. * @see serialize()
  596. */
  597. function setMode( $mode )
  598. {
  599. $this->mode = strtolower( $mode );
  600. if( !empty( $this->elements ) )
  601. {
  602. $cnt = count( $this->elements );
  603. for( $i=0; $i < $cnt; $i++ )
  604. {
  605. $this->elements[$i]->setMode( $mode );
  606. }
  607. }
  608. }
  609. /**
  610. * sets the current submitted state of the form. Set this to true if you want the form
  611. * to pick up its submitted data. It will pass on this information to all elements that
  612. * have been added so far, and new ones inherit it too.
  613. *
  614. * @access public
  615. * @param bool $state True if it has been submitted, false otherwise (default).
  616. * @see isSubmitted()
  617. * @see submitted
  618. */
  619. function setSubmitted( $state )
  620. {
  621. if( $state == true )
  622. {
  623. $eventState = $this->triggerEvent( 'Submit' );
  624. if( $eventState === false )
  625. return false;
  626. }
  627. $this->submitted = $state;
  628. if( !empty( $this->elements ) )
  629. {
  630. $cnt = count( $this->elements );
  631. for( $i=0; $i < $cnt; $i++ )
  632. {
  633. $this->elements[$i]->setSubmitted( $state );
  634. }
  635. }
  636. return $state;
  637. }
  638. /**
  639. * sets the method for the request
  640. *
  641. * @access public
  642. * @param string $method GET or POST
  643. * @see method
  644. * @uses setAttribute()
  645. */
  646. function setMethod( $method )
  647. {
  648. $method = strtolower( $method );
  649. if( $method != 'get' && $method != 'post' )
  650. {
  651. return patErrorManager::raiseError(
  652. PATFORMS_ERROR_INVALID_METHOD,
  653. 'Unknown method "'.$method.'". Currently only GET and POST are supported as patForms methods.'
  654. );
  655. }
  656. $this->setAttribute( 'method', $method );
  657. return true;
  658. }
  659. /**
  660. * sets the action for the form
  661. *
  662. * This is a only a wrapper for setAttribute()
  663. *
  664. * @access public
  665. * @param string $action
  666. * @see setAttribute()
  667. */
  668. function setAction( $action )
  669. {
  670. return $this->setAttribute( 'action', $action );
  671. }
  672. /**
  673. * Sets the AutoFinalize mode for the form. The AutoFinalize mode will tell patForms to
  674. * finalize all elements after the form has been validated successfully.
  675. *
  676. * @access public
  677. * @param boolean $mode Whether to activate the AutoFinalize mode (true) or not (false).
  678. * @return boolean $success True if okay, a patError object otherwise.
  679. * @see finalizeForm()
  680. */
  681. function setAutoFinalize( $mode )
  682. {
  683. if( !is_bool( $mode ) )
  684. {
  685. return patErrorManager::raiseError(
  686. PATFORMS_ERROR_PARAMETER_NO_BOOL,
  687. 'The setAutoFinalize() method requires a boolean value ( true or false ) as parameter.'
  688. );
  689. }
  690. if( isset( $this ) && is_a( $this, 'patForms' ) )
  691. {
  692. $this->autoFinalize = $mode;
  693. }
  694. else
  695. {
  696. patForms::setStaticProperty( 'autoFinalize', $mode );
  697. }
  698. return true;
  699. }
  700. /**
  701. * Wrapper method that adds a filter to all elements
  702. * of the form at once instead of having to do it for
  703. * each element.
  704. *
  705. * @access public
  706. * @param object &$filter The filter object to apply
  707. * @see patForms_Element::applyFilter()
  708. * @todo add error management and docs once the element's applyFilter method has too
  709. */
  710. function applyFilter( &$filter )
  711. {
  712. if( empty( $this->elements ) )
  713. return true;
  714. $cnt = count( $this->elements );
  715. for( $i = 0; $i < $cnt; $i++ )
  716. {
  717. $this->elements[$i]->applyFilter( $filter );
  718. }
  719. }
  720. /**
  721. * creates a new patForms object and returns it; this method is made to be called statically
  722. * to be able to create a new patForms object from anywhere.
  723. *
  724. * @access public
  725. * @param array $formDefinition Optional form definition for elements that will be added to the form
  726. * @param array $attributes The attributes to set for the form itself
  727. * @return object patForms $form The new patForms object.
  728. * @todo it should be possible to pass Rule definitions, so they can be loaded and added automatically.
  729. */
  730. function &createForm( $formDefinition = null, $attributes = null )
  731. {
  732. $form = &new patForms();
  733. if( $attributes != null )
  734. {
  735. $form->setAttributes( $attributes );
  736. }
  737. if( $formDefinition === null )
  738. return $form;
  739. foreach( $formDefinition as $name => $element )
  740. {
  741. if( !isset( $element["filters"] ) )
  742. {
  743. $element["filters"] = null;
  744. }
  745. if( !isset( $element["children"] ) )
  746. {
  747. $element["children"] = null;
  748. }
  749. $el = &$form->createElement( $name, $element["type"], $element["attributes"], $element["filters"], $element["children"] );
  750. if( isset( $element["renderer"] ) ) {
  751. $el->setRenderer( $element["renderer"] );
  752. }
  753. $result = $form->addElement( $el );
  754. if (patErrorManager::isError( $result )) {
  755. return $result;
  756. }
  757. }
  758. return $form;
  759. }
  760. /**
  761. * add a custom validation rule
  762. *
  763. * @access public
  764. * @param object patForms_Rule validation rule
  765. * @param integer time to apply rule (before or after built-in validation)
  766. * @param boolean apply the rule, even if the form is invalid
  767. * @param boolean should form get revalidated (not implemented yet)
  768. * @return boolean currently always true
  769. */
  770. function addRule( &$rule, $time = PATFORMS_RULE_AFTER_VALIDATION, $invalid = false, $revalidate = false )
  771. {
  772. $rule->prepareRule( $this );
  773. $this->_rules[] = array(
  774. 'rule' => &$rule,
  775. 'time' => $time,
  776. 'invalid' => $invalid,
  777. 'revalidate' => $revalidate
  778. );
  779. }
  780. /**
  781. * patForms PHP5 constructor - processes some intitialization tasks like merging the currently
  782. * set static properties with the internal properties.
  783. *
  784. * @access public
  785. */
  786. function __construct()
  787. {
  788. foreach( $this->staticProperties as $staticProperty => $setMethod )
  789. {
  790. $propValue = patForms::getStaticProperty( $staticProperty );
  791. if( patErrorManager::isError( $propValue ) )
  792. continue;
  793. $this->$setMethod( $propValue );
  794. }
  795. // initialize patForms internal attribute collection
  796. $this->loadAttributeDefaults();
  797. }
  798. /**
  799. * patForms pre-PHP5 constructor - does nothing for the moment except being a wrapper
  800. * for the PHP5 contructor for older PHP versions support.
  801. *
  802. * @access public
  803. */
  804. function patForms()
  805. {
  806. patForms::__construct();
  807. }
  808. /**
  809. * sets a renderer object that will be used to render
  810. * the form.
  811. *
  812. * @access public
  813. * @param object &$renderer The renderer object
  814. * @return mixed $success True on success, patError object otherwise.
  815. * @see createRenderer()
  816. * @see renderForm()
  817. */
  818. function setRenderer( &$renderer, $args = array() )
  819. {
  820. if( !is_object( $renderer ) )
  821. {
  822. return patErrorManager::raiseError(
  823. PATFORMS_ERROR_INVALID_RENDERER,
  824. 'You can only set a patForms_Renderer object with the setRenderer() method, "'.gettype( $renderer ).'" given.'
  825. );
  826. }
  827. $this->renderer = &$renderer;
  828. if( isset( $args['includeElements'] ) && $args['includeElements'] === true )
  829. {
  830. // check all elements - there may be some that need
  831. // renderers too, so we give them the same renderer if
  832. // they don't already have one.
  833. $cnt = count( $this->elements );
  834. for( $i = 0; $i < $cnt; $i++ )
  835. {
  836. if( $this->elements[$i]->usesRenderer && !is_object( $this->elements[$i]->renderer ) )
  837. {
  838. $this->elements[$i]->setRenderer( $renderer );
  839. }
  840. }
  841. }
  842. return true;
  843. }
  844. /**
  845. * sets a storage container object that will be used to store data
  846. *
  847. * @access public
  848. * @param object patForms_Storage
  849. * @see createStorage()
  850. */
  851. function setStorage( &$storage )
  852. {
  853. if( !is_object( $storage ) )
  854. {
  855. return patErrorManager::raiseError(
  856. PATFORMS_ERROR_INVALID_STORAGE,
  857. 'You can only set a patForms_Storage object with the setStorage() method, "'.gettype( $storage ).'" given.'
  858. );
  859. }
  860. $this->registerEventHandlerObject( $storage,
  861. array(
  862. 'onInit' => 'loadEntry',
  863. 'onSuccess' => 'storeEntry'
  864. )
  865. );
  866. }
  867. /**
  868. * renders the form with the renderer that was set via the {@link setRenderer()}
  869. * method.
  870. *
  871. * WARNING: This is still in alpha state!
  872. *
  873. * Should this method return a reference??
  874. * The return value could contain large blocks of HTML or large arrays!
  875. * Do we want to copy these?
  876. *
  877. * @access public
  878. * @param mixed $args arguments that will be passed to the renderer
  879. * @return mixed $form The rendered form, or false if failed.
  880. */
  881. function renderForm( $args = null )
  882. {
  883. if( $this->renderer === null )
  884. {
  885. return patErrorManager::raiseError(
  886. PATFORMS_ERROR_NO_RENDERER_SET,
  887. 'Form cannot be rendered, you have to set a renderer first via the setRenderer() method.'
  888. );
  889. }
  890. // form is not submitted, or auto-validation is disabled => render it
  891. if( !$this->isSubmitted() || $this->autoValidate !== true )
  892. {
  893. $this->triggerEvent( 'Init' );
  894. return $this->renderer->render( $this, $args );
  895. }
  896. $this->validateForm();
  897. return $this->renderer->render( $this, $args );
  898. }
  899. /**
  900. * Validates all elements of the form.
  901. *
  902. * @access public
  903. * @param boolean Flag to indicate, whether form should be validated again, if it already has been validated.
  904. * @return boolean True if all elements could be validated, false otherwise.
  905. * @see finishForm()
  906. */
  907. function validateForm( $revalidate = false )
  908. {
  909. if( $this->validated && !$revalidate )
  910. return $this->valid;
  911. $valid = true;
  912. /**
  913. * validate custom rules
  914. */
  915. if( !$this->_applyRules( PATFORMS_RULE_BEFORE_VALIDATION ) )
  916. {
  917. $valid = false;
  918. }
  919. /**
  920. * validate elements
  921. */
  922. if( $valid === true )
  923. {
  924. $cnt = count( $this->elements );
  925. for( $i = 0; $i < $cnt; ++$i )
  926. {
  927. if( !$this->elements[$i]->validate() )
  928. {
  929. $valid = false;
  930. }
  931. }
  932. }
  933. /**
  934. * validate custom rules
  935. */
  936. if( !$this->_applyRules( PATFORMS_RULE_AFTER_VALIDATION, $valid ) )
  937. {
  938. $valid = false;
  939. }
  940. if( $valid === true && $this->autoFinalize === true )
  941. $this->finalizeForm();
  942. $this->valid = $valid;
  943. $this->validated = true;
  944. if( $valid === true )
  945. {
  946. $this->_announce( 'status', 'validated' );
  947. $event = 'Success';
  948. }
  949. else
  950. {
  951. $this->_announce( 'status', 'error' );
  952. $event = 'Error';
  953. }
  954. $this->triggerEvent( $event );
  955. return $this->valid;
  956. }
  957. /**
  958. * apply rules
  959. *
  960. * @access private
  961. * @param integer time of validation
  962. * @param boolean form is valid
  963. * @return boolean rules are valid or not
  964. * @todo add documentation
  965. */
  966. function _applyRules( $time, $isValid = true )
  967. {
  968. $valid = true;
  969. $cnt = count( $this->_rules );
  970. for ($i = 0; $i < $cnt; $i++) {
  971. // wrong time
  972. if (( $this->_rules[$i]['time'] & $time ) != $time) {
  973. continue;
  974. }
  975. if (!$isValid && !$this->_rules[$i]['invalid']) {
  976. continue;
  977. }
  978. $result = $this->_rules[$i]['rule']->applyRule( $this, PATFORMS_RULE_AFTER_VALIDATION );
  979. if( $result === false ) {
  980. $valid = false;
  981. }
  982. }
  983. return $valid;
  984. }
  985. /**
  986. * Finalizes the form by telling each fom element to finalize - finalizing means to
  987. * process any tasks that need to be done after the form has been validated, like
  988. * deleting any temporary files or whatever an element needs to do at that point.
  989. *
  990. * @access public
  991. * @return bool $success Wether all elements could be finalized
  992. * @see validateForm()
  993. */
  994. function finalizeForm()
  995. {
  996. $success = true;
  997. $cnt = count( $this->elements );
  998. for( $i = 0; $i < $cnt; ++$i )
  999. {
  1000. if( !$this->elements[$i]->finalize() )
  1001. {
  1002. patErrorManager::raiseWarning(
  1003. PATFORMS_ERROR_ELEMENT_NOT_FINALIZED,
  1004. 'Element "'.$this->elements[$i]->elementName.'" could not be finalized. See the element error messages for more details.'
  1005. );
  1006. $success = false;
  1007. }
  1008. }
  1009. return $success;
  1010. }
  1011. /**
  1012. * creates a new renderer from the patForms renderer collection and returns it.
  1013. *
  1014. * @access public
  1015. * @param string The name of the renderer to create - have a look at the Renderer/ subfolder for a list of available renderers.
  1016. * @return object patForms_Renderer The renderer object, or error object
  1017. */
  1018. function &createRenderer( $name )
  1019. {
  1020. return patForms::_createModule( 'Renderer', $name );
  1021. }
  1022. /**
  1023. * creates a new storage container and returns it.
  1024. *
  1025. * @access public
  1026. * @param string The name of the storage to create - have a look at the Storage/ subfolder for a list of available storage containers.
  1027. * @return object patForms_Storage The storage container, or error object
  1028. */
  1029. function &createStorage( $name )
  1030. {
  1031. return patForms::_createModule( 'Storage', $name );
  1032. }
  1033. /**
  1034. * Creates a new filter and returns it.
  1035. *
  1036. * You may pass an array as second parameter that contains
  1037. * parameters for the filter. patForms will check for setter methods
  1038. * for all keys and set the corresponding values.
  1039. *
  1040. * This eases the creating of simple filter objects.
  1041. *
  1042. * @access public
  1043. * @param string The name of the filter to create - have a look at the Filter/ subfolder for a list of available filters.
  1044. * @param array Optional parameters for the filter, if you provide a parameter, make sure the filter implements a set[Paramname]() method.
  1045. * This will be automated with interceptors in the PHP5 version of patForms
  1046. * @return object patForms_Filter The filter, or error object
  1047. */
  1048. function &createFilter( $name, $params = null )
  1049. {
  1050. $filter = &patForms::_createModule( 'Filter', $name );
  1051. if( !is_array( $params ) )
  1052. {
  1053. return $filter;
  1054. }
  1055. foreach( $params as $param => $value )
  1056. {
  1057. $setter = 'set' . ucfirst( $param );
  1058. if( method_exists( $filter, $setter ) )
  1059. {
  1060. $filter->$setter( $value );
  1061. }
  1062. }
  1063. return $filter;
  1064. }
  1065. /**
  1066. * creates a new rule from the patForms rule collection and returns it.
  1067. *
  1068. * If your rules are not located in patForms/Rule you have to load and
  1069. * instantiate them on your own.
  1070. *
  1071. * @access public
  1072. * @param string The name of the rule to create - have a look at the Rule/ subfolder for a list of available rules.
  1073. * @param string The id of the rule, needed if the rule uses client side actions.
  1074. * @return object patForms_Rule The rule object, or error object
  1075. */
  1076. static function &createRule( $name, $id = null )
  1077. {
  1078. $rule = &patForms::_createModule( 'Rule', $name );
  1079. if( $id != null )
  1080. {
  1081. $rule->setId( $id );
  1082. }
  1083. return $rule;
  1084. }
  1085. /**
  1086. * creates a new observer from the patForms observer collection and returns it.
  1087. *
  1088. * If your observers are not located in patForms/Observer you have to load and
  1089. * instantiate them on your own.
  1090. *
  1091. * @access public
  1092. * @param string The name of the observer to create - have a look at the Observer/ subfolder for a list of available observers.
  1093. * @return object patForms_Observer The observer object, or error object
  1094. */
  1095. function &createObserver( $name )
  1096. {
  1097. $observer = &patForms::_createModule( 'Observer', $name );
  1098. return $observer;
  1099. }
  1100. /**
  1101. * creates a new module for patForms
  1102. *
  1103. * @access private
  1104. * @param string $type type of the module. Possible values are 'Renderer', 'Rule'
  1105. * @param string $name The name of the renderer to create - have a look at the renderers/ subfolder for a list of available renderers.
  1106. * @return object $module The module object, or an error object
  1107. */
  1108. function &_createModule( $type, $name )
  1109. {
  1110. $baseFile = PATFORMS_INCLUDE_PATH . '/'.$type.'.php';
  1111. $baseClass = 'patForms_'.$type;
  1112. // if there is an underscore in the module name, we want
  1113. // to load the module from a subfolder, so we transform
  1114. // all underscores to slashes.
  1115. $pathName = $name;
  1116. if( strstr( $pathName, '_' ) )
  1117. {
  1118. $pathName = str_replace( '_', '/', $name );
  1119. }
  1120. $moduleFile = PATFORMS_INCLUDE_PATH . '/'.$type.'/'.$pathName.'.php';
  1121. $moduleClass = 'patForms_'.$type.'_'.$name;
  1122. if( !class_exists( $baseClass, FALSE ) )
  1123. {
  1124. if( !file_exists( $baseFile ) )
  1125. {
  1126. return patErrorManager::raiseError(
  1127. PATFORMS_ERROR_NO_MODULE_BASE_FILE,
  1128. $type .' base file could not be found',
  1129. 'Tried to load base file in path "'.$baseFile.'"'
  1130. );
  1131. }
  1132. include_once $baseFile;
  1133. }
  1134. if( !class_exists( $moduleClass, true ) )
  1135. {
  1136. if( !file_exists( $moduleFile ) )
  1137. {
  1138. if (defined('PATFORMS_LOCAL_INCLUDE_PATH')) {
  1139. $localModuleClass = PATFORMS_LOCAL_INCLUDE_PATH."/".$type."/".$pathName.".php";
  1140. if (file_exists($localModuleClass)) {
  1141. include_once $localModuleClass;
  1142. $module = new $moduleClass();
  1143. return $module;
  1144. }
  1145. }
  1146. return patErrorManager::raiseError(
  1147. PATFORMS_ERROR_MODULE_NOT_FOUND,
  1148. $type.' "'.$name.'" file "'.$moduleFile. '" could not be found.'
  1149. );
  1150. }
  1151. include_once $moduleFile;
  1152. }
  1153. $module = new $moduleClass();
  1154. return $module;
  1155. }
  1156. /**
  1157. * adds an element to the form - has to be a patForms_Element object. Use the {@link createElement()}
  1158. * method to create a new element object. Also takes care of passing on the form's configuration
  1159. * including the mode, format and submitted flags to the element.
  1160. *
  1161. * @access public
  1162. * @param object &$element The patForms_Element object to add to this form.
  1163. * @return bool $success True if everything went well, false otherwise.
  1164. * @see patForms_Element
  1165. * @see createElement()
  1166. */
  1167. function addElement( &$element )
  1168. {
  1169. if( !is_object( $element ) )
  1170. {
  1171. return patErrorManager::raiseError(
  1172. PATFORMS_ERROR_ELEMENT_IS_NO_OBJECT,
  1173. 'The addElement() method expects an element object, "'.gettype( $element ).'" given.'
  1174. );
  1175. }
  1176. if( patErrorManager::isError( $element ) )
  1177. {
  1178. return patErrorManager::raiseError(
  1179. PATFORMS_ERROR_UNEXPECTED_ERROR,
  1180. 'The element you are trying to add is a patError object, and not a patForms element object.'
  1181. );
  1182. }
  1183. if( !$element->getId() ) {
  1184. $element->setId( $this->getElementId() );
  1185. }
  1186. $element->setMode( $this->getMode() );
  1187. $element->setFormat( $this->getFormat() );
  1188. $element->setSubmitted( $this->isSubmitted() );
  1189. $element->setLocale( $this->getLocale() );
  1190. $this->elements[] =& $element;
  1191. return true;
  1192. }
  1193. /**
  1194. * replaces an element in the form
  1195. *
  1196. * @access public
  1197. * @param object $element The patForms_Element object to be replaced
  1198. * @param object &$replace The element that will replace the old element
  1199. * @return bool $success True if everything went well, false otherwise.
  1200. * @see patForms_Element
  1201. * @see addElement()
  1202. */
  1203. function replaceElement( $element, &$replace )
  1204. {
  1205. if( !is_object( $replace ) ) {
  1206. return patErrorManager::raiseError(
  1207. PATFORMS_ERROR_ELEMENT_IS_NO_OBJECT,
  1208. 'The addElement() method expects an element object, "'.gettype( $replace ).'" given.'
  1209. );
  1210. }
  1211. if( patErrorManager::isError( $replace ) ) {
  1212. return patErrorManager::raiseError(
  1213. PATFORMS_ERROR_UNEXPECTED_ERROR,
  1214. 'The element you are trying to add is a patError object, and not a patForms element object.'
  1215. );
  1216. }
  1217. if (is_object($element)) {
  1218. $element = $element->getId();
  1219. }
  1220. $cnt = count($this->elements);
  1221. for ($i = 0; $i < $cnt; $i++) {
  1222. if ($this->elements[$i]->getId() === $element) {
  1223. if( !$replace->getId() ) {
  1224. $replace->setId( $this->getElementId() );
  1225. }
  1226. $replace->setMode( $this->getMode() );
  1227. $replace->setFormat( $this->getFormat() );
  1228. $replace->setSubmitted( $this->isSubmitted() );
  1229. $replace->setLocale( $this->getLocale() );
  1230. $this->elements[$i] = &$replace;
  1231. return true;
  1232. }
  1233. // the current element is a container
  1234. if (method_exists($this->elements[$i], 'replaceElement')) {
  1235. $result = $this->elements[$i]->replaceElement($element, $replace);
  1236. if ($result === true) {
  1237. return $result;
  1238. }
  1239. }
  1240. }
  1241. return false;
  1242. }
  1243. /**
  1244. * Get an element by its name.
  1245. *
  1246. * @access public
  1247. * @param string $name name of the element
  1248. * @return object patForms element
  1249. * @deprecated please use patForms::getElementByName() instead
  1250. */
  1251. function &getElement( $name )
  1252. {
  1253. return $this->getElementByName( $name );
  1254. }
  1255. /**
  1256. * Get an element by its name.
  1257. *
  1258. * @access public
  1259. * @param string $name name of the element
  1260. * @return mixed either a patForms element or an array containing patForms elements
  1261. * @see getElementById()
  1262. */
  1263. function &getElementByName( $name )
  1264. {
  1265. if( $name == '__form' ) {
  1266. return $this;
  1267. }
  1268. $elements = array();
  1269. $cnt = count( $this->elements );
  1270. for ($i = 0; $i < $cnt; $i++) {
  1271. if ($this->elements[$i]->getName() == $name) {
  1272. $elements[] = &$this->elements[$i];
  1273. continue;
  1274. }
  1275. if (method_exists($this->elements[$i], 'getElementById')) {
  1276. patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
  1277. $result = &$this->elements[$i]->getElementByName($name);
  1278. patErrorManager::popExpect();
  1279. if (!patErrorManager::isError($result)) {
  1280. if (is_array($result)) {
  1281. $cnt2 = count( $result );
  1282. for ($j = 0; $j < $cnt2; $j++) {
  1283. $elements[] = &$result[$j];
  1284. }
  1285. } else {
  1286. $elements[] = &$result;
  1287. }
  1288. }
  1289. }
  1290. }
  1291. switch( count( $elements ) )
  1292. {
  1293. case 0:
  1294. $r = patErrorManager::raiseError(
  1295. PATFORMS_ERROR_ELEMENT_NOT_FOUND,
  1296. 'Element '.$name.' could not be found.'
  1297. );
  1298. return $r;
  1299. break;
  1300. case 1:
  1301. return $elements[0];
  1302. break;
  1303. default:
  1304. return $elements;
  1305. break;
  1306. }
  1307. }
  1308. /**
  1309. * Get an element by its id.
  1310. *
  1311. * @access public
  1312. * @param string $id id of the element
  1313. * @return object patForms element
  1314. */
  1315. function &getElementById( $id )
  1316. {
  1317. $cnt = count( $this->elements );
  1318. for( $i = 0; $i < $cnt; $i++ )
  1319. {
  1320. if( $this->elements[$i]->getId() == $id ) {
  1321. return $this->elements[$i];
  1322. }
  1323. if (method_exists($this->elements[$i], 'getElementById')) {
  1324. patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
  1325. $result = &$this->elements[$i]->getElementById($id);
  1326. patErrorManager::popExpect();
  1327. if (!patErrorManager::isError($result)) {
  1328. return $result;
  1329. }
  1330. }
  1331. }
  1332. return patErrorManager::raiseError(
  1333. PATFORMS_ERROR_ELEMENT_NOT_FOUND,
  1334. 'Element '.$name.' could not be found.'
  1335. );
  1336. }
  1337. /**
  1338. * Get all elements of the form
  1339. *
  1340. * @access public
  1341. * @return array all elements of the form
  1342. */
  1343. function &getElements()
  1344. {
  1345. return $this->elements;
  1346. }
  1347. /**
  1348. * Creates a new form element and returns a reference to it.
  1349. *
  1350. * The optional $filters array has to be in the following format:
  1351. *
  1352. * <pre>
  1353. * array(
  1354. * array(
  1355. * 'filter' => 'Multiplier',
  1356. * 'params' => array( 'multiplier' => 6 )
  1357. * )
  1358. * )
  1359. * </pre>
  1360. *
  1361. * @access public
  1362. * @param string $name The name of the element
  1363. * @param string $type The type of the element; for a list of possible elements, have a look at the elements/ subfolder of the patForms package.
  1364. * @param array $attributes Attributes for the element
  1365. * @param array $filters Optional filters that will be applied
  1366. * @return object patForms_Element $element The element object, or patError if failed.
  1367. */
  1368. function &createElement( $name, $type, $attributes, $filters = null, $children = null )
  1369. {
  1370. $element =& patForms::_createModule( 'Element', $type );
  1371. if( patErrorManager::isError( $element ) )
  1372. {
  1373. return $element;
  1374. }
  1375. $attributes['name'] = $name;
  1376. if( !isset( $attributes['id'] ) ) {
  1377. $attributes['id'] = patForms::getElementId();
  1378. }
  1379. // add default attributes - do this the 'silent' way be checking whether
  1380. // the element supports the given attribute, as the element throws a notice
  1381. // if it does not support it - this is not expected from default attributes.
  1382. foreach( patForms::getStaticProperty( 'defaultAttributes' ) as $attributeName => $attributeValue )
  1383. {
  1384. if( !$element->hasAttribute( $attributeName ) )
  1385. {
  1386. continue;
  1387. }
  1388. $element->setAttribute( $attributeName, $attributeValue );
  1389. }
  1390. // set the given attributes normally
  1391. $success = $element->setAttributes( $attributes );
  1392. if( patErrorManager::isError( $success ) )
  1393. {
  1394. return $success;
  1395. }
  1396. if (is_array($children)) {
  1397. foreach ($children as $child) {
  1398. $childName = $child['attributes']['name'];
  1399. $childEl = &patForms::createElement($childName, $child['type'], $child['attributes']);
  1400. if( isset( $child["renderer"] ) ) {
  1401. $childEl->setRenderer( $child["renderer"] );
  1402. }
  1403. $element->addElement($childEl);
  1404. }
  1405. }
  1406. $success = $element->_init();
  1407. if( patErrorManager::isError( $success ) ) {
  1408. return $success;
  1409. }
  1410. // if we don't have any filters to add, we're done
  1411. if( !is_array( $filters ) )
  1412. {
  1413. return $element;
  1414. }
  1415. $cnt = count( $filters );
  1416. for( $i = 0; $i < $cnt; $i++ )
  1417. {
  1418. $params = isset( $filters[$i]['params'] ) ? $filters[$i]['params'] : null;
  1419. $filter = &patForms::createFilter( $filters[$i]['filter'], $params );
  1420. if( patErrorManager::isError( $filter ) )
  1421. {
  1422. continue;
  1423. }
  1424. $element->applyFilter( $filter );
  1425. }
  1426. return $element;
  1427. }
  1428. /**
  1429. * retrieves the validation errors from all elements in the form. Use this if the validateForm()
  1430. * method returned false.
  1431. *
  1432. * @access public
  1433. * q
  1434. * @return array $errors Array containing an array with validation errors for each element in the form.
  1435. * @todo replace __form with the name of the form, once attributes are implemented
  1436. */
  1437. function getValidationErrors($withElements = true)
  1438. {
  1439. $found = false;
  1440. $errors = array();
  1441. if( !empty( $this->validationErrors ) )
  1442. {
  1443. $errors['__form'] = $this->validationErrors;
  1444. $found = true;
  1445. }
  1446. if ($withElements === false) {
  1447. return $errors;
  1448. }
  1449. $cnt = count( $this->elements );
  1450. for( $i = 0; $i < $cnt; ++$i )
  1451. {
  1452. $name = $this->elements[$i]->getAttribute( 'name' );
  1453. if( $name === false )
  1454. {
  1455. continue;
  1456. }
  1457. $elementErrors = $this->elements[$i]->getValidationErrors();
  1458. if( empty( $elementErrors ) )
  1459. continue;
  1460. $errors[$name] = $elementErrors;
  1461. $found = true;
  1462. }
  1463. if( $found )
  1464. return $errors;
  1465. return false;
  1466. }
  1467. /**
  1468. * retrieves the values for all elements in the form.
  1469. *
  1470. * @access public
  1471. * @param array desired fields
  1472. * @param integer Mode that should be used to return values in groups
  1473. * @return array The values for all elements, as elementname => elementvalue.
  1474. *
  1475. * @todo remove the ugly Group check and replace with something better
  1476. * @todo implement something similar for getValidation errors
  1477. */
  1478. function getValues( $fields = null, $type = PATFORMS_VALUES_NESTED )
  1479. {
  1480. $values = array();
  1481. $cnt = count( $this->elements );
  1482. for( $i = 0; $i < $cnt; ++$i )
  1483. {
  1484. $name = $this->elements[$i]->getAttribute( 'name' );
  1485. if( $name === false ) {
  1486. continue;
  1487. }
  1488. if( is_array( $fields ) && !in_array( $name, $fields ) ) {
  1489. continue;
  1490. }
  1491. $tmpVal = $this->elements[$i]->getValue();
  1492. if (!is_array($tmpVal) || $this->elements[$i]->elementName != 'Group') {
  1493. $values[$name] = $tmpVal;
  1494. continue;
  1495. }
  1496. switch ($type) {
  1497. case PATFORMS_VALUES_FLATTENED:
  1498. $values = array_merge($values, $tmpVal);
  1499. break;
  1500. case PATFORMS_VALUES_PREFIXED:
  1501. foreach ($tmpVal as $key => $val) {
  1502. $values[$name.'_'.$key] = $val;
  1503. }
  1504. break;
  1505. case PATFORMS_VALUES_NESTED:
  1506. default:
  1507. $values[$name] = $tmpVal;
  1508. break;
  1509. }
  1510. }
  1511. return $values;
  1512. }
  1513. /**
  1514. * sets the values for all elements in the form. Use this to fill your form with external
  1515. * data, like a db query. Caution: if you do this and set the form to submitted, the values
  1516. * will be overwritten by any values present in the $_GET or $_POST variables.
  1517. *
  1518. * @access public
  1519. * @param array $values The values for all elements, as elementname => elementvalue.
  1520. */
  1521. function setValues( $values, $overrideUserInput = false )
  1522. {
  1523. patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
  1524. if(is_array($values)) {
  1525. foreach ($values as $elName => $value) {
  1526. $el = &$this->getElementByName($elName);
  1527. if (patErrorManager::isError($el)) {
  1528. continue;
  1529. }
  1530. if ($overrideUserInput === true) {
  1531. $el->setValue($value);
  1532. } else {
  1533. $el->setDefaultValue($value);
  1534. }
  1535. }
  1536. }
  1537. patErrorManager::popExpect();
  1538. return true;
  1539. }
  1540. /**
  1541. * retrieves the current mode of the form
  1542. *
  1543. * @access public
  1544. * @return string $mode The current form mode
  1545. * @see setMode()
  1546. * @see $mode
  1547. */
  1548. function getMode()
  1549. {
  1550. return $this->mode;
  1551. }
  1552. /**
  1553. * returns the locale that is currently set for the form.
  1554. *
  1555. * @access public
  1556. * @return string $locale The locale.
  1557. * @see setLocale()
  1558. * @see $locale
  1559. */
  1560. function getLocale()
  1561. {
  1562. return $this->locale;
  1563. }
  1564. /**
  1565. * retrieves the current format of the form
  1566. *
  1567. * @access public
  1568. * @return string $format The current form format
  1569. * @see setFormat()
  1570. * @see format
  1571. */
  1572. function getFormat()
  1573. {
  1574. return $this->format;
  1575. }
  1576. /**
  1577. * retrieves the current method of the form
  1578. *
  1579. * @access public
  1580. * @return string $method The request method
  1581. * @see setMethod()
  1582. */
  1583. function getMethod()
  1584. {
  1585. return $this->getAttribute( 'method' );
  1586. }
  1587. /**
  1588. * retrieves the current action of the form
  1589. *
  1590. * @access public
  1591. * @return string $action Action of the form
  1592. * @see setAction()
  1593. */
  1594. function getAction()
  1595. {
  1596. $action = $this->getAttribute( 'action' );
  1597. if( !empty( $action ) )
  1598. return $action;
  1599. return $_SERVER['PHP_SELF'];
  1600. }
  1601. /**
  1602. * adds an atribute to the form's attribute collection. If the attribute
  1603. * already exists, it is overwritten.
  1604. *
  1605. * @access public
  1606. * @param string $attributeName The name of the attribute to add
  1607. * @param string $atributeValue The value of the attribute
  1608. */
  1609. function setAttribute( $attributeName, $attributeValue )
  1610. {
  1611. if( !isset( $this->attributeDefinition[$attributeName] ) )
  1612. {
  1613. patErrorManager::raiseNotice(
  1614. PATFORMS_NOTICE_ATTRIBUTE_NOT_SUPPORTED,
  1615. "The attribute '".$attributeName."' is not supported by the form, skipped it. [".get_class( $this )."]"
  1616. );
  1617. return true;
  1618. }
  1619. $this->attributes[$attributeName] = $attributeValue;
  1620. return true;
  1621. }
  1622. /**
  1623. * adds several attributes at once to the form's attribute collection.
  1624. * Any existing attributes will be overwritten.
  1625. *
  1626. * @access public
  1627. * @param array $attributes The attributes to add
  1628. * @see setAttribute()
  1629. */
  1630. function setAttributes( $attributes )
  1631. {
  1632. if( !is_array( $attributes ) )
  1633. {
  1634. return patErrorManager::raiseError(
  1635. PATFORMS_NOTICE_ARRAY_EXPECTED,
  1636. "setAttributes: array expected"
  1637. );
  1638. }
  1639. foreach( $attributes as $attributeName => $attributeValue )
  1640. {
  1641. $this->setAttribute( $attributeName, $attributeValue );
  1642. }
  1643. return true;
  1644. }
  1645. /**
  1646. * retrieves the value of a form attribute.
  1647. *
  1648. * @access public
  1649. * @param string $attribute The name of the attribute to retrieve
  1650. * @return mixed $attributeValue The value of the attribute, or false if it does not exist in the attributes collection.
  1651. * @see setAttribute()
  1652. */
  1653. function getAttribute( $attribute )
  1654. {
  1655. if( !isset( $this->attributes[$attribute] ) )
  1656. {
  1657. return false;
  1658. }
  1659. return $this->attributes[$attribute];
  1660. }
  1661. /**
  1662. * retrieves all attributes of the form, or only the specified attributes.
  1663. *
  1664. * @access public
  1665. * @param array $attributes Optional: The names of the attributes to retrieve. Only the attributes that exist will be returned.
  1666. * @return array $result The attributes
  1667. * @see getAttribute()
  1668. */
  1669. function getAttributes( $attributes = array() )
  1670. {
  1671. if( empty( $attributes ) )
  1672. {
  1673. return $this->attributes;
  1674. }
  1675. $result = array();
  1676. foreach( $attributes as $attribute )
  1677. {
  1678. if( $attributeValue = $this->getAttribute( $attribute ) )
  1679. {
  1680. $result[$attribute] = $attributeValue;
  1681. }
  1682. }
  1683. return $result;
  1684. }
  1685. /**
  1686. * Loads the default attribute values into the attributes collection. Done directly
  1687. * on startup (in the consructor).
  1688. *
  1689. * The action defaults to the path of the current script, with session
  1690. * ID appended automatically, if SID has been defined.
  1691. *
  1692. * @access public
  1693. * @return bool $success Always returns true.
  1694. * @see $attributeDefaults
  1695. */
  1696. function loadAttributeDefaults()
  1697. {
  1698. foreach( $this->attributeDefinition as $attributeName => $attributeDef )
  1699. {
  1700. if( isset( $attributeDef['default'] ) )
  1701. {
  1702. $this->attributes[$attributeName] = $attributeDef['default'];
  1703. }
  1704. if( $attributeName == 'action' )
  1705. {
  1706. $this->attributes[$attributeName] = $_SERVER['PHP_SELF'];
  1707. /**
  1708. * session has been started, append session ID
  1709. */
  1710. if( defined( 'SID' ) )
  1711. $this->attributes[$attributeName] .= '?' . SID;
  1712. }
  1713. }
  1714. return true;
  1715. }
  1716. /**
  1717. * retrieves the form's current submitted state.
  1718. *
  1719. * If autoValidate is used, it will check for the submitVar and
  1720. * set the submitted flag accordingly
  1721. *
  1722. * @access public
  1723. * @return bool $state True if it has been submitted, false otherwise.
  1724. * @see setSubmitted(), setAutoValidate()
  1725. * @see submitted
  1726. */
  1727. function isSubmitted()
  1728. {
  1729. if( $this->submitted === true )
  1730. {
  1731. return true;
  1732. }
  1733. if( !isset( $this->submitVar ) )
  1734. {
  1735. return false;
  1736. }
  1737. if( !$this->autoValidate )
  1738. {
  1739. return false;
  1740. }
  1741. if( isset( $_GET[$this->submitVar] ) || isset( $_POST[$this->submitVar] ) )
  1742. {
  1743. $this->setSubmitted( true );
  1744. }
  1745. return $this->submitted;
  1746. }
  1747. /**
  1748. * Creates a new patForms_Creator object
  1749. *
  1750. * @static
  1751. * @access public
  1752. * @return object $creator The creator object, or a patError object on failure
  1753. */
  1754. function createCreator( $type )
  1755. {
  1756. return patForms::_createModule( 'Creator', $type );
  1757. }
  1758. /**
  1759. * get the element name of the form
  1760. *
  1761. * @access public
  1762. * @return string name of the form
  1763. */
  1764. function getElementName()
  1765. {
  1766. return $this->elementName;
  1767. }
  1768. /**
  1769. * get next error offset
  1770. *
  1771. * @access public
  1772. * @return integer
  1773. */
  1774. function getErrorOffset( $requiredCodes = 100 )
  1775. {
  1776. $offset = $this->nextErrorOffset;
  1777. $this->nextErrorOffset = $this->nextErrorOffset + $requiredCodes;
  1778. return $offset;
  1779. }
  1780. /**
  1781. * add error codes and messages for validator method
  1782. *
  1783. * @access public
  1784. * @param array defintions
  1785. * @param integer offset for the error codes
  1786. */
  1787. function addValidatorErrorCodes( $defs, $offset = 1000 )
  1788. {
  1789. foreach( $defs as $lang => $codes )
  1790. {
  1791. if( !isset( $this->validatorErrorCodes[$lang] ) )
  1792. {
  1793. $this->validatorErrorCodes[$lang] = array();
  1794. }
  1795. foreach( $codes as $code => $message )
  1796. {
  1797. $this->validatorErrorCodes[$lang][($offset+$code)] = $message;
  1798. }
  1799. }
  1800. }
  1801. /**
  1802. * add a validation error to the whole form
  1803. *
  1804. * This can be achieved by adding a validation rule to the form.
  1805. *
  1806. * @access public
  1807. * @param integer $code
  1808. * @param array $vars fill named placeholder with values
  1809. * @return boolean $result true on success
  1810. * @see addRule()
  1811. */
  1812. function addValidationError( $code, $vars = array() )
  1813. {
  1814. $error = false;
  1815. $lang = $this->locale;
  1816. $element = $this->getElementName();
  1817. // find error message for selected language
  1818. while( true )
  1819. {
  1820. // error message matches language code
  1821. if( isset( $this->validatorErrorCodes[$lang][$code] ) )
  1822. {
  1823. $error = array( "element" => $element, "code" => $code, "message" => $this->validatorErrorCode

Large files files are truncated, but you can click here to view the full file