PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/contentmanager/code/trunk/administrator/components/com_contentmanager/libraries/jxtended/form/view.php

https://bitbucket.org/eddieajau/the-art-of-joomla-archive
PHP | 894 lines | 440 code | 92 blank | 362 comment | 74 complexity | 436659cad21479365e2ead005777c4a4 MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: view.php 160 2009-07-09 00:06:09Z eddieajau $
  4. * @package JXtended.Libraries
  5. * @subpackage Form
  6. * @copyright Copyright (C) 2008 - 2009 JXtended, LLC. All rights reserved.
  7. * @license GNU General Public License <http://www.gnu.org/copyleft/gpl.html>
  8. * @link http://jxtended.com
  9. */
  10. defined('JPATH_BASE') or die;
  11. jximport2('joomla.registry.registry');
  12. jximport2('jxtended.form.field');
  13. if(!defined('FORM_FIELD_INCLUDE_PATH')) {
  14. define('FORM_FIELD_INCLUDE_PATH', dirname(__FILE__).DS.'fields');
  15. }
  16. /**
  17. * Form view object
  18. *
  19. * @package JXtended.Libraries
  20. * @subpackage Forms
  21. */
  22. class JXFormView extends JRegistry
  23. {
  24. /**
  25. * Loaded form field type opjects
  26. * @access private
  27. * @var array
  28. */
  29. var $_fieldTypes = array();
  30. /**
  31. * Folders to search for form field objects
  32. * @access private
  33. * @var array
  34. */
  35. var $_fieldFolders = array();
  36. /**
  37. * Form action URL
  38. * @access private
  39. * @var string
  40. */
  41. var $_action = null;
  42. /**
  43. * Form id
  44. * @access private
  45. * @var string
  46. */
  47. var $_id = null;
  48. /**
  49. * Form name
  50. * @access private
  51. * @var string
  52. */
  53. var $_name = null;
  54. /**
  55. * Form is multi-part (includes an upload control)
  56. * @access private
  57. * @var boolean
  58. */
  59. var $_multipart;
  60. /**
  61. * Form Descriptor
  62. * @access private
  63. * @var array
  64. */
  65. var $_descriptor = array();
  66. var $_layouts = null;
  67. /**
  68. * Constructor
  69. *
  70. * @access protected
  71. * @param string $descriptor XML Form descriptor string
  72. * @param string $data INI Form value data string
  73. * @return void
  74. * @since 1.5
  75. */
  76. function __construct($descriptor = null, $data = null)
  77. {
  78. parent::__construct('_default');
  79. $this->_load($descriptor, false);
  80. if (trim($data)) {
  81. $this->loadINI($data);
  82. }
  83. JHTML::addIncludePath(dirname(__FILE__).DS.'html');
  84. }
  85. /**
  86. * @param string String data, or a file name
  87. * @param boolean
  88. */
  89. function _load($data, $fromFile = false)
  90. {
  91. // Initialize variables
  92. $result = false;
  93. if ($data) {
  94. $xml = & JFactory::getXMLParser('Simple');
  95. $loaded = $fromFile ? $xml->loadFile($data) : $xml->loadString($data);
  96. if ($loaded) {
  97. if ($fieldsets = & $xml->document->fields) {
  98. foreach ($fieldsets as $fields)
  99. {
  100. $this->loadFieldsXML($fields, true);
  101. $result = true;
  102. }
  103. }
  104. if ($action =& $xml->document->action[0]) {
  105. $this->setAction($action->data());
  106. }
  107. //$this->setName($xml->document->attributes('control'));
  108. }
  109. }
  110. return $result;
  111. }
  112. /**
  113. * Loads a form view xml file and set form descriptor information
  114. *
  115. * @access public
  116. * @param string $path Path to the form view xml file
  117. * @return boolean True if successful
  118. * @since 1.5
  119. */
  120. function loadFormFile($path)
  121. {
  122. return $this->_load($path, true);
  123. }
  124. /**
  125. * Loads a form view xml string and set form descriptor information
  126. *
  127. * @access public
  128. * @param string $descriptor XML Form descriptor string
  129. * @return boolean True if successful
  130. * @since 1.5
  131. */
  132. function loadFormString($descriptor)
  133. {
  134. return $this->_load($descriptor, false);
  135. }
  136. /**
  137. * Set a field value
  138. *
  139. * @access public
  140. * @param string The name of the field
  141. * @param string The value of the field
  142. * @param string The form field group
  143. * @return string The set value
  144. * @since 1.5
  145. */
  146. function set($key, $value = '', $group = '_default')
  147. {
  148. $this->setValue($group.'.'.$key, (string) $value);
  149. return $this->getValue($group.'.'.$key);
  150. }
  151. /**
  152. * Get a field value
  153. *
  154. * @access public
  155. * @param string The name of the field
  156. * @param mixed The default value of the field
  157. * @param string The form field group
  158. * @return string The field value
  159. * @since 1.5
  160. */
  161. function get($key, $default = '', $group = '_default')
  162. {
  163. $value = $this->getValue($group.'.'.$key);
  164. $result = (empty($value) && ($value !== 0) && ($value !== '0')) ? $default : $value;
  165. return $result;
  166. }
  167. /**
  168. * Sets a default value if not alreay assigned
  169. *
  170. * @access public
  171. * @param string The name of the field
  172. * @param mixed The default value of the field
  173. * @param string The form field group
  174. * @return string The field value
  175. * @since 1.5
  176. */
  177. function def($key, $value = '', $group = '_default')
  178. {
  179. return $this->set($key, $this->get($key, (string) $value, $group), $group);
  180. }
  181. /**
  182. * Bind data to the form
  183. *
  184. * @access public
  185. * @param mixed $data Array or Object
  186. * @param string The form field group
  187. * @return boolean True if the data was successfully bound
  188. * @since 1.5
  189. */
  190. function bind($data, $group = '_default')
  191. {
  192. if (is_array($data)) {
  193. return $this->loadArray($data, $group);
  194. } elseif (is_object($data)) {
  195. return $this->loadObject($data, $group);
  196. }
  197. // Not an object or an array... can't help you :)
  198. return false;
  199. }
  200. /**
  201. * Get the form action URL
  202. *
  203. * @access public
  204. * @param string $default Default action URL if internal action URL is not set
  205. * @return string Form action URL
  206. * @since 1.5
  207. */
  208. function getAction($default = null)
  209. {
  210. return ($this->_action) ? $this->_action : $default;
  211. }
  212. /**
  213. * Set the form action URL
  214. *
  215. * @access public
  216. * @param string $action Form action URL to set
  217. * @return void
  218. * @since 1.5
  219. */
  220. function setAction($action)
  221. {
  222. $this->_action = $action;
  223. }
  224. /**
  225. * Get the form id
  226. *
  227. * @access public
  228. * @param string $default Default id if internal id is not set
  229. * @return string Form id
  230. * @since 1.5
  231. */
  232. function getId($default = null)
  233. {
  234. return ($this->_id) ? $this->_id : $default;
  235. }
  236. /**
  237. * Get the form name
  238. *
  239. * @access public
  240. * @param string $default Default name if internal name is not set
  241. * @return string Form name
  242. * @since 1.5
  243. */
  244. function getName($default = null)
  245. {
  246. return ($this->_name) ? $this->_name : $default;
  247. }
  248. /**
  249. * Set the form id
  250. *
  251. * @access public
  252. * @param string $value Form id to set
  253. * @return void
  254. * @since 1.5
  255. */
  256. function setId($value)
  257. {
  258. $this->_id = $value;
  259. }
  260. /**
  261. * Set the form name
  262. *
  263. * @access public
  264. * @param string $value Form tag name
  265. * @return void
  266. * @since 1.5
  267. */
  268. function setName($value)
  269. {
  270. $this->_name = $value;
  271. }
  272. /**
  273. * Loads form fields from an XML element optionally reseting fields before loading new ones.
  274. *
  275. * @access public
  276. * @param object $xml An XML object
  277. * @param boolean $reset True to reset fields before adding new ones
  278. * @return void
  279. * @since 1.5
  280. */
  281. function loadFieldsXML(&$xml, $reset = true)
  282. {
  283. if (is_object($xml))
  284. {
  285. $group = ($xml->attributes('group')) ? $xml->attributes('group') : '_default';
  286. if ($reset) {
  287. $this->setFields($xml->children(), $group);
  288. } else {
  289. $this->addFields($xml->children(), $group);
  290. }
  291. if ($folder = $xml->attributes('addfieldfolder')) {
  292. $this->addFieldFolder(JPATH_ROOT.$folder);
  293. }
  294. }
  295. }
  296. /**
  297. * Add a field to a group
  298. *
  299. * @access public
  300. * @param object $field Form field object to add
  301. * @param string $group Group to add the field to
  302. * @return void
  303. * @since 1.5
  304. */
  305. function addField(&$field, $group = '_default')
  306. {
  307. $this->_descriptor[$group][] = &$field;
  308. }
  309. /**
  310. * Add an array of fields to a group
  311. *
  312. * @access public
  313. * @param array $fields Array of form field objects to add
  314. * @param string $group Group to add the fields to
  315. * @return void
  316. * @since 1.5
  317. */
  318. function addFields($fields, $group = '_default')
  319. {
  320. $this->_descriptor[$group] = array_merge($this->_descriptor[$group], $fields);
  321. }
  322. /**
  323. * Set an array of fields to a group replacing any currently set fields
  324. *
  325. * @access public
  326. * @param array $fields Array of form field objects to set
  327. * @param string $group Group to set the fields to
  328. * @return void
  329. * @since 1.5
  330. */
  331. function setFields($fields, $group = '_default')
  332. {
  333. $this->_descriptor[$group] = $fields;
  334. }
  335. /**
  336. * Render the field group in plain format
  337. *
  338. * @access public
  339. * @param string $legend The fieldset legend
  340. * @param string $controlName The control name for the form field group
  341. * @param string $group The form field group
  342. * @param string $options Named array of options for display (include|exclude array or comma list of field names)
  343. * @return string HTML
  344. * @since 1.5
  345. */
  346. function render($controlName = 'jxform', $group = '_default', $options = array())
  347. {
  348. if (!isset($this->_descriptor[$group])) {
  349. return false;
  350. }
  351. $fields = $this->getFields($controlName, $group);
  352. if (!count($fields)) {
  353. return;
  354. }
  355. // white-list: only include a list of fields
  356. $includeList = null;
  357. if (isset($options['include']))
  358. {
  359. if (is_array($options['include'])) {
  360. $includeList = &$options['include'];
  361. } else {
  362. $includeList = explode(',', $options['include']);
  363. }
  364. }
  365. // black-list: include all but fields listed
  366. $excludeList = null;
  367. if (isset($options['exclude']))
  368. {
  369. // only include a list of fields
  370. if (is_array($options['exclude'])) {
  371. $excludeList = &$options['exclude'];
  372. } else {
  373. $excludeList = explode(',', $options['exclude']);
  374. }
  375. }
  376. $html = array ();
  377. $hidden = array();
  378. foreach ($fields as $field)
  379. {
  380. if ($includeList and !$excludeList and !in_array($field->name, $includeList)) {
  381. continue;
  382. }
  383. else if ($excludeList and !$includeList and in_array($field->name, $excludeList)) {
  384. continue;
  385. }
  386. if (!$field->get('field')) {
  387. continue;
  388. }
  389. if ($field->type == 'Hidden')
  390. {
  391. $hidden[] = $field->get('field');
  392. }
  393. else
  394. {
  395. $html[] = $field->get('label');
  396. $html[] = $field->get('field');
  397. }
  398. }
  399. return implode("\n", $html)."\n".implode("\n", $hidden);
  400. }
  401. /**
  402. * Render the field group to an ordered list
  403. *
  404. * @access public
  405. * @param string $legend The fieldset legend
  406. * @param string $controlName The control name for the form field group
  407. * @param string $group The form field group
  408. * @return string HTML
  409. * @since 1.5
  410. */
  411. function renderToOL($legend = null, $controlName = 'jxform', $group = '_default')
  412. {
  413. if (!isset($this->_descriptor[$group])) {
  414. return false;
  415. }
  416. $fields = $this->getFields($controlName, $group);
  417. if (!count($fields)) {
  418. return;
  419. }
  420. $html = array ();
  421. $html[] = '<fieldset>';
  422. // If legend is set add the fieldset legend
  423. if ($legend) {
  424. $html[] = ' <legend>'.$legend.'</legend>';
  425. }
  426. $html[] = ' <ol>';
  427. foreach ($fields as $field)
  428. {
  429. if (!$field->get('field')) {
  430. continue;
  431. }
  432. $html[] = ' <li>';
  433. $html[] = ' '.$field->get('label');
  434. $html[] = ' '.$field->get('field');
  435. $html[] = ' </li>';
  436. }
  437. $html[] = ' </ol>';
  438. $html[] = '</fieldset>';
  439. return implode("\n", $html);
  440. }
  441. /**
  442. * Render the field group to a table
  443. *
  444. * @access public
  445. * @param string $legend The fieldset legend
  446. * @param string $controlName The control name for the form field group
  447. * @param string $group The form field group
  448. * @return string HTML
  449. * @since 1.5
  450. */
  451. function renderToFieldset($legend = null, $controlName = 'jxform', $group = '_default', $options = array())
  452. {
  453. if (!isset($this->_descriptor[$group])) {
  454. return false;
  455. }
  456. $html = array ();
  457. $html[] = '<fieldset>';
  458. // If legend is set add the fieldset legend
  459. if ($legend) {
  460. $html[] = ' <legend>'.$legend.'</legend>';
  461. }
  462. $html[] = $this->renderToTable($controlName, $group);
  463. $html[] = '</fieldset>';
  464. return implode("\n", $html);
  465. }
  466. /**
  467. * Render the field group to a table
  468. *
  469. * @access public
  470. * @param string $legend The fieldset legend
  471. * @param string $controlName The control name for the form field group
  472. * @param string $group The form field group
  473. * @param string $options Named array of options for display (include|exclude array or comma list of field names)
  474. * @return string HTML
  475. * @since 1.5
  476. */
  477. function renderToTable($controlName = 'jxform', $group = '_default', $options = array())
  478. {
  479. if (!isset($this->_descriptor[$group])) {
  480. return false;
  481. }
  482. $fields = $this->getFields($controlName, $group);
  483. if (!count($fields)) {
  484. return;
  485. }
  486. // white-list: only include a list of fields
  487. $includeList = null;
  488. if (isset($options['include']))
  489. {
  490. if (is_array($options['include'])) {
  491. $includeList = &$options['include'];
  492. } else {
  493. $includeList = explode(',', $options['include']);
  494. }
  495. }
  496. // black-list: include all but fields listed
  497. $excludeList = null;
  498. if (isset($options['exclude']))
  499. {
  500. // only include a list of fields
  501. if (is_array($options['exclude'])) {
  502. $excludeList = &$options['exclude'];
  503. } else {
  504. $excludeList = explode(',', $options['exclude']);
  505. }
  506. }
  507. $html = array ();
  508. $hidden = array();
  509. $html[] = ' <table class="admintable">';
  510. foreach ($fields as $field)
  511. {
  512. if ($includeList and !$excludeList and !in_array($field->name, $includeList)) {
  513. continue;
  514. }
  515. else if ($excludeList and !$includeList and in_array($field->name, $excludeList)) {
  516. continue;
  517. }
  518. if (!$field->get('field')) {
  519. continue;
  520. }
  521. if ($field->type == 'Hidden')
  522. {
  523. $hidden[] = $field->get('field');
  524. }
  525. else
  526. {
  527. $html[] = ' <tr>';
  528. $html[] = ' <td scope="row" class="key">'.$field->get('label').'</td>';
  529. $html[] = ' <td>'.$field->get('field').'</td>';
  530. $html[] = ' </tr>';
  531. }
  532. }
  533. $html[] = ' </table>';
  534. return implode("\n", $html).implode("\n", $hidden);
  535. }
  536. /**
  537. * Return the form head string
  538. *
  539. * @access public
  540. * @return string Form header eg. <form>
  541. * @since 1.5
  542. */
  543. function getHead()
  544. {
  545. jximport2('joomla.filter.output');
  546. $id = $this->getId();
  547. $name = $this->getName($id);
  548. $action = JFilterOutput::ampReplace($this->getAction());
  549. $enctype = $this->_multipart ? ' enctype="multipart/form-data"' : '';
  550. return '<form id="'.$id.'-form" class="form-validate" name="'.$name.'" method="post" action="'.$action.'"'.$enctype.'>';
  551. }
  552. /**
  553. * Return the form foot string
  554. *
  555. * @access public
  556. * @return string Form footer eg. </form>
  557. * @since 1.5
  558. */
  559. function getFoot($tokens = true, $randomize = false)
  560. {
  561. jximport2('joomla.utilities.utility');
  562. $html = null;
  563. if ($tokens) {
  564. $token = JUtility::getToken();
  565. $random = md5(rand());
  566. $rand = rand(1000, 9999);
  567. $rand2 = rand(1000, 9999);
  568. if ($randomize) {
  569. if (rand() % 2) {
  570. $html .= '<input type="hidden" name="'.$token.'" value="'.$rand.'" />';
  571. $html .= '<input type="hidden" name="'.$random.'" value="'.$rand2.'" />';
  572. } else {
  573. $html .= '<input type="hidden" name="'.$random.'" value="'.$rand2.'" />';
  574. $html .= '<input type="hidden" name="'.$token.'" value="'.$rand.'" />';
  575. }
  576. } else {
  577. $html .= '<input type="hidden" name="'.$token.'" value="'.$rand.'" />';
  578. $html .= '<input type="hidden" name="'.$random.'" value="'.$rand2.'" />';
  579. }
  580. }
  581. $html .= '<input type="hidden" name="JXForm_id" value="'.$this->_id.'" />';
  582. $html .= '</form>';
  583. return $html;
  584. }
  585. /**
  586. * Return number of form fields for a given group
  587. *
  588. * @access public
  589. * @return mixed Boolean false if no fields exist or integer number of fields that exist
  590. * @since 1.5
  591. */
  592. function getNumFields($group = '_default')
  593. {
  594. if (!isset($this->_descriptor[$group]) || !count($this->_descriptor[$group])) {
  595. return false;
  596. } else {
  597. return count($this->_descriptor[$group]);
  598. }
  599. }
  600. /**
  601. * Get the number of form fields in each group
  602. *
  603. * @access public
  604. * @return array Associative array of form field groups => number of fields in the group
  605. * @since 1.5
  606. */
  607. function getGroups()
  608. {
  609. if (!is_array($this->_descriptor)) {
  610. return false;
  611. }
  612. $results = array();
  613. foreach ($this->_descriptor as $name => $group)
  614. {
  615. $results[$name] = $this->getNumFields($name);
  616. }
  617. return $results;
  618. }
  619. /**
  620. * Get a node
  621. *
  622. * @param string The attribute to search on
  623. * @param string The attribute value to match
  624. * @param string $group The form field group
  625. *
  626. * @return mixed
  627. */
  628. function &getNode($attribute, $value, $group = '_default')
  629. {
  630. $result = false;
  631. if (isset($this->_descriptor[$group])) {
  632. foreach ($this->_descriptor[$group] as $i => $node) {
  633. if ($node->attributes($attribute) === $value) {
  634. $result = &$node;
  635. break;
  636. }
  637. }
  638. }
  639. return $result;
  640. }
  641. /**
  642. * Returns a named array of labels and values
  643. *
  644. * @access public
  645. * @param string $group The form field group
  646. * @return array Associative array
  647. * @since 1.5
  648. */
  649. function getData($group = '_default')
  650. {
  651. if (!isset($this->_descriptor[$group])) {
  652. return false;
  653. }
  654. $results = array();
  655. foreach ($this->_descriptor[$group] as $node) {
  656. $results[$node->attributes('label')] = $this->get($node->attributes('name'), $node->attributes('default'));
  657. }
  658. return $results;
  659. }
  660. /**
  661. * Render a form field group to an associative array by field name
  662. *
  663. * @access public
  664. * @param string $controlName The control name for the form field group
  665. * @param string $group The form field group
  666. * @return array Associative array of rendered Form Field object by field name
  667. * @since 1.5
  668. */
  669. function getFields($controlName = 'jxform', $group = '_default')
  670. {
  671. if (!isset($this->_descriptor[$group])) {
  672. return false;
  673. }
  674. $results = array();
  675. foreach ($this->_descriptor[$group] as $node) {
  676. $results[$node->attributes('name')] = $this->getField($node, $controlName, $group);
  677. }
  678. /*
  679. for ($i = 0, $n = count($this->_descriptor[$group]); $i < $n; $i++)
  680. {
  681. $node = &$this->_descriptor[$group][$i];
  682. $results[$node->attributes('name')] = $this->getField($node, $controlName, $group);
  683. }
  684. */
  685. return $results;
  686. }
  687. /**
  688. * Render a form field
  689. *
  690. * @access public
  691. * @param object $node An JXFormField object
  692. * @param string $controlName The field control name
  693. * @param string $group The form field group
  694. * @return object Rendered Form Field object
  695. * @since 1.5
  696. */
  697. function getField(&$node, $controlName = 'jxform', $group = '_default')
  698. {
  699. // get the field type
  700. $type = $node->attributes('type');
  701. // get the field value
  702. // TODO: this is a fudge to get around loadObject that spans all groups
  703. $value = $this->get($node->attributes('name'), $node->attributes('default')/*, $group*/);
  704. // load the field type object
  705. $field =& $this->loadFieldType($type);
  706. // field type could not be loaded -- just return some basic information
  707. if ($field === false) {
  708. $field =& $this->loadFieldType('text');
  709. }
  710. return $field->render($node, $value, $controlName);
  711. }
  712. /**
  713. * Loads a form field type object
  714. *
  715. * @access public
  716. * @param string Form field type
  717. * @return mixed Form field type object or boolean false on failure
  718. * @since 1.5
  719. */
  720. function &loadFieldType($type, $new = false)
  721. {
  722. $false = false;
  723. $signature = md5($type);
  724. if(isset($this->_fieldTypes[$signature]) && $new === false) {
  725. return $this->_fieldTypes[$signature];
  726. }
  727. if(!class_exists('JXFieldType')) {die('oops');
  728. jximport2('jxtended.form.field');
  729. }
  730. if ($pos = strpos($type, '_'))
  731. {
  732. // what we are doing here is some smart loading of derived field types
  733. $baseType = substr($type, 0, $pos);
  734. $this->loadFieldType($baseType);
  735. }
  736. $typeClass = 'JXFieldType'.ucfirst($type);
  737. if(!class_exists($typeClass))
  738. {
  739. if(isset($this->_fieldFolders)) {
  740. $folders = $this->_fieldFolders;
  741. } else {
  742. $folders = array();
  743. }
  744. // Last we push the base include path into the queue
  745. array_push($folders, $this->getIncludePath());
  746. // TODO: Can we use the built in JPath::find method here?
  747. $found = false;
  748. $n = count($folders);
  749. for ($i = $n - 1; $i >= 0; $i--)
  750. {
  751. $typeFile = sprintf('%s'.DS.'%s.php', $folders[$i], str_replace('_', DS, $type));
  752. if (file_exists($typeFile))
  753. {
  754. require_once $typeFile;
  755. $found = true;
  756. break;
  757. }
  758. }
  759. if (!$found) {
  760. return $false;
  761. }
  762. }
  763. if(!class_exists($typeClass)) {
  764. return $false;
  765. }
  766. $this->_fieldTypes[$signature] = new $typeClass($this);
  767. return $this->_fieldTypes[$signature];
  768. }
  769. /**
  770. * Add a folder where JXFormView should search for form field objects
  771. *
  772. * You may either pass a string or an array of strings.
  773. *
  774. * JXFormView will be searching for form field objects in the same
  775. * order you added them. If the object cannot be found in the custom folders,
  776. * it will look in the base include path.
  777. *
  778. * @access public
  779. * @param mixed $folder Folder or folders to search for form field objects.
  780. * @return void
  781. * @since 1.5
  782. */
  783. function addFieldFolder($folder)
  784. {
  785. if(is_array($folder)) {
  786. $this->_fieldFolders = array_merge($this->_fieldFolders, $folder);
  787. } else {
  788. array_push($this->_fieldFolders, $folder);
  789. }
  790. }
  791. /**
  792. * Get the base form field object include path
  793. *
  794. * @access public
  795. * @return string
  796. * @since 1.5
  797. */
  798. function getIncludePath()
  799. {
  800. return FORM_FIELD_INCLUDE_PATH;
  801. }
  802. }