PageRenderTime 55ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/content/code/trunk/administrator/components/com_artofcontent/libraries/jxtended/form/form.php

https://bitbucket.org/eddieajau/the-art-of-joomla-archive
PHP | 999 lines | 489 code | 131 blank | 379 comment | 157 complexity | 8d701274858f83f7dbfeef46b2602cc9 MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: form.php 484 2010-12-20 23:40:27Z 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
  8. * @link http://jxtended.com
  9. */
  10. defined('JPATH_BASE') or die;
  11. juimport('jxtended.form.formfield');
  12. /**
  13. * Form Class for JXtended Libraries.
  14. *
  15. * This class implements a robust API for constructing, populating,
  16. * filtering, and validating forms. It uses XML definitions to
  17. * construct form fields and a variety of field and rule classes
  18. * to render and validate the form.
  19. *
  20. * @package JXtended.Libraries
  21. * @subpackage Forms
  22. * @version 1.1
  23. */
  24. class JForm extends JObject
  25. {
  26. /**
  27. * The form name.
  28. *
  29. * @var string
  30. */
  31. protected $_name;
  32. /**
  33. * An array of options for form groups.
  34. *
  35. * @var array
  36. */
  37. protected $_fieldsets = array();
  38. /**
  39. * Form groups containing field objects.
  40. *
  41. * @var array
  42. */
  43. protected $_groups = array();
  44. /**
  45. * Form data containing field values.
  46. *
  47. * @var array
  48. */
  49. protected $_data = array();
  50. /**
  51. * Form options.
  52. *
  53. * @var array
  54. */
  55. protected $_options = array();
  56. /**
  57. * Method to get an instance of a form.
  58. *
  59. * @param string $name The name of the form.
  60. * @param string $data The name of an XML file or an XML string.
  61. * @param string $file Flag to toggle whether the $data is a file path or a string.
  62. * @param array $options An array of options to pass to the form.
  63. * @return object A JForm instance.
  64. */
  65. public static function &getInstance($data, $name = 'form', $file = true, $options = array())
  66. {
  67. static $instances;
  68. if ($instances == null) {
  69. $instances = array();
  70. }
  71. // Only load the form once.
  72. if (!isset($instances[$name])) {
  73. // Instantiate the form.
  74. $instances[$name] = new JForm($options);
  75. // Set the form name.
  76. $instances[$name]->setName($name);
  77. // Load the data.
  78. if ($file) {
  79. $instances[$name]->load($data, true, true);
  80. } else {
  81. $instances[$name]->load($data, false, true);
  82. }
  83. }
  84. return $instances[$name];
  85. }
  86. /**
  87. * Method to construct the object on instantiation.
  88. *
  89. * @param array $options An array of form options.
  90. * @return void
  91. */
  92. public function __construct($options = array())
  93. {
  94. // Set the options if specified.
  95. $this->_options['array'] = array_key_exists('array', $options) ? $options['array'] : false;
  96. }
  97. /**
  98. * Method to get the form name.
  99. *
  100. * @return string The name of the form.
  101. */
  102. public function getName()
  103. {
  104. return $this->_name;
  105. }
  106. /**
  107. * Method to set the form name.
  108. *
  109. * @param string $name The new name of the form.
  110. * @return void
  111. */
  112. public function setName($name)
  113. {
  114. $this->_name = $name;
  115. }
  116. /**
  117. * Method to recursively bind values to form fields.
  118. *
  119. * @param mixed $data An array or object of form values.
  120. * @param string $group The group to bind the fields to.
  121. * @return boolean True on success, false otherwise.
  122. */
  123. public function bind($data, $limit = null)
  124. {
  125. // The data must be an object or array.
  126. if (!is_object($data) && !is_array($data)) {
  127. return false;
  128. }
  129. // Convert objects to arrays.
  130. if (is_object($data)) {
  131. // Handle a JRegistry/JParameter object.
  132. if ($data instanceof JRegistry) {
  133. $data = $data->toArray();
  134. }
  135. // Handle a JObject.
  136. elseif ($data instanceof JObject) {
  137. $data = $data->getProperties();
  138. }
  139. // Handle other types of objects.
  140. else {
  141. $data = (array)$data;
  142. }
  143. }
  144. // Iterate through the groups.
  145. foreach ($this->_groups as $group => $fields) {
  146. // Bind if no group is specified or if the group matches the current group.
  147. if ($limit === null || ($limit !== null && $group === $limit)) {
  148. // Iterate through the values.
  149. foreach ($data as $k => $v) {
  150. // If the field name matches the name of the group and the value is not scalar, recurse.
  151. if ($k == $group && !is_scalar($v) && !is_resource($v)) {
  152. $this->bind($v, $group);
  153. } else {
  154. // Bind the value to the field if it exists.
  155. if (isset($this->_groups[$group][$k]) && is_object($this->_groups[$group][$k])) {
  156. $this->_data[$group][$k] = $v;
  157. }
  158. }
  159. }
  160. }
  161. }
  162. return true;
  163. }
  164. /**
  165. * Method to load the form description from a file or string.
  166. *
  167. * If $data is a file name, $file must be set to true. The reset option
  168. * works on a group basis. If the XML file or string references groups
  169. * that have already been created they will be replaced with the fields
  170. * in the new file unless the $reset parameter has been set to false.
  171. *
  172. * @param string $data The name of an XML file or an XML string.
  173. * @param string $file Flag to toggle whether the $data is a file path or a string.
  174. * @param string $reset Flag to toggle whether the form description should be reset.
  175. * @return boolean True on success, false otherwise.
  176. */
  177. public function load($data, $file = true, $reset = true)
  178. {
  179. $return = false;
  180. // Make sure we have data.
  181. if (!empty($data)) {
  182. // Get the XML parser and load the data.
  183. $parser = &JFactory::getXMLParser('Simple');
  184. // If the data is a file, load the XML from the file.
  185. if ($file) {
  186. // If we were not given the absolute path of a form file, attempt to find one.
  187. if (!is_file($data)) {
  188. jimport('joomla.filesystem.path');
  189. $data = JPath::find(self::addFormPath(), strtolower($data).'.xml');
  190. }
  191. // Attempt to load the XML file.
  192. $loaded = $parser->loadFile($data);
  193. }
  194. // Load the data as a string.
  195. else {
  196. $loaded = $parser->loadString($data);
  197. }
  198. // Make sure the XML was loaded.
  199. if ($loaded) {
  200. // Check if any groups exist.
  201. if (isset($parser->document->fields)) {
  202. // Load the form groups.
  203. foreach ($parser->document->fields as $group) {
  204. $this->loadFieldsXML($group, $reset);
  205. $return = true;
  206. }
  207. }
  208. // Check if an action is set.
  209. if ($parser->document->attributes('action') && $reset) {
  210. $this->setAction($parser->document->attributes('action'));
  211. }
  212. // Check if a name is set.
  213. if ($parser->document->attributes('name') && $reset) {
  214. $this->setName($parser->document->attributes('name'));
  215. }
  216. // Check if an id is set.
  217. if ($parser->document->attributes('id') && $reset) {
  218. $this->setId($parser->document->attributes('id'));
  219. }
  220. }
  221. }
  222. return $return;
  223. }
  224. /**
  225. * Method to load form descriptions from a complete folder.
  226. *
  227. * This function loads all files that have the via $name defined prefix
  228. * in the folders defined by addIncludePath()
  229. *
  230. * @param string $name The prefix-name of the XML files
  231. * @return boolean True on success, false otherwise.
  232. * @since 1.6
  233. */
  234. public function loadFolder($name)
  235. {
  236. $return = false;
  237. jimport('joomla.filesystem.folder');
  238. $files = JFolder::files($this->addFormPath(), $name, false, true);
  239. if (count($files)) {
  240. foreach($files as $file) {
  241. $result = $this->load($file, true, true);
  242. }
  243. } else {
  244. $result = true;
  245. }
  246. return $result;
  247. }
  248. /**
  249. * Method to recursively filter data for form fields.
  250. *
  251. * @param array $data The data to filter.
  252. * @param string $limit An optional group to limit the filtering to.
  253. * @return array An array of filtered data.
  254. */
  255. public function filter($data, $limit = null)
  256. {
  257. // Initialise variables.
  258. $return = array();
  259. // The data must be an object or array.
  260. if (!is_object($data) && !is_array($data)) {
  261. return false;
  262. }
  263. // Get some system objects.
  264. $config = JFactory::getConfig();
  265. $user = JFactory::getUser();
  266. // Convert objects to arrays.
  267. if (is_object($data)) {
  268. // Handle a JRegistry/JParameter object.
  269. if ($data instanceof JRegistry) {
  270. $data = $data->toArray();
  271. }
  272. // Handle a JObject.
  273. elseif ($data instanceof JObject) {
  274. $data = $data->getProperties();
  275. }
  276. // Handle other types of objects.
  277. else {
  278. $data = (array)$data;
  279. }
  280. }
  281. // Static input filters for specific settings.
  282. static $noHtmlFilter;
  283. static $safeHtmlFilter;
  284. // Get the safe HTML filter if not set.
  285. if (is_null($safeHtmlFilter)) {
  286. $safeHtmlFilter = &JFilterInput::getInstance(null, null, 1, 1);
  287. }
  288. // Get the no HTML filter if not set.
  289. if (is_null($noHtmlFilter)) {
  290. $noHtmlFilter = &JFilterInput::getInstance(/* $tags, $attr, $tag_method, $attr_method, $xss_auto */);
  291. }
  292. // Iterate through the groups.
  293. foreach ($this->_groups as $group => $fields) {
  294. // Filter if no group is specified or if the group matches the current group.
  295. if ($limit === null || ($limit !== null && $group === $limit)) {
  296. // If the group name matches the name of a group in the data and the value is not scalar, recurse.
  297. if (isset($data[$group]) && !is_scalar($data[$group]) && !is_resource($data[$group])) {
  298. $return[$group] = $this->filter($data[$group], $group);
  299. } else {
  300. // Filter the fields.
  301. foreach ($fields as $name => $field)
  302. {
  303. // Get the field information.
  304. $filter = $field->attributes('filter');
  305. // Check for a value to filter.
  306. if (isset($data[$name])) {
  307. // Handle the different filter options.
  308. switch (strtoupper($filter)) {
  309. case 'UNSET':
  310. // Do nothing.
  311. break;
  312. case 'RAW':
  313. // No Filter.
  314. $return[$name] = $data[$name];
  315. break;
  316. case 'SAFEHTML':
  317. // Filter safe HTML.
  318. $return[$name] = $safeHtmlFilter->clean($data[$name], 'string');
  319. break;
  320. case 'SERVER_UTC':
  321. // Convert a date to UTC based on the server timezone offset.
  322. if (intval($data[$name])) {
  323. $offset = $config->getValue('config.offset');
  324. $date = JFactory::getDate($data[$name], $offset);
  325. $return[$name] = $date->toMySQL();
  326. }
  327. break;
  328. case 'USER_UTC':
  329. // Convert a date to UTC based on the user timezone offset.
  330. if (intval($data[$name])) {
  331. $offset = $user->getParam('timezone', $config->getValue('config.offset'));
  332. $date = JFactory::getDate($data[$name], $offset);
  333. $return[$name] = $date->toMySQL();
  334. }
  335. break;
  336. default:
  337. // Check for a callback filter.
  338. if (strpos($filter, '::') !== false && is_callable(explode('::', $filter))) {
  339. // Filter using the callback method.
  340. $return[$name] = call_user_func(explode('::', $filter), $data[$name]);
  341. } else if (function_exists($filter)) {
  342. // Filter using the callback function.
  343. $return[$name] = call_user_func($filter, $data[$name]);
  344. } else {
  345. // Filter using JFilterInput. All HTML code is filtered by default.
  346. $return[$name] = $noHtmlFilter->clean($data[$name], $filter);
  347. }
  348. break;
  349. }
  350. }
  351. }
  352. }
  353. }
  354. }
  355. return $return;
  356. }
  357. /**
  358. * Method to validate form data.
  359. *
  360. * Validation warnings will be pushed into JForm::_errors and should be
  361. * retrieved with JForm::getErrors() when validate returns boolean false.
  362. *
  363. * @param array $data An array of field values to validate.
  364. * @param string $limit An option group to limit the validation to.
  365. * @return mixed Boolean on success, JException on error.
  366. */
  367. public function validate($data, $limit = null)
  368. {
  369. $return = true;
  370. $data = (array)$data;
  371. // Check if the group exists.
  372. if ($limit !== null && !isset($this->_groups[$limit])) {
  373. // The group that was supposed to be filtered does not exist.
  374. return new JException(JText::sprintf('LIBRARIES FORM VALIDATOR GROUP NOT FOUND', $limit), 0, E_ERROR);
  375. }
  376. // Get a validator object.
  377. juimport('jxtended.form.formvalidator');
  378. $validator = new JFormValidator();
  379. // Iterate through the groups.
  380. foreach ($this->_groups as $group => $fields) {
  381. // Filter if no group is specified or if the group matches the current group.
  382. if ($limit === null || ($limit !== null && $group === $limit)) {
  383. // If the group name matches the name of a group in the data and the value is not scalar, pass the group.
  384. if (isset($data[$group]) && !is_scalar($data[$group]) && !is_resource($data[$group])) {
  385. $results = $validator->validate($this->_groups[$group], $data[$group]);
  386. } else {
  387. // Run the validator over the group.
  388. $results = $validator->validate($this->_groups[$group], $data);
  389. }
  390. // Check for a error.
  391. if (JError::isError($results)) {
  392. return new JException($results->getMessage(), 0, E_ERROR);
  393. }
  394. // Check the validation results.
  395. if (count($results)) {
  396. // Get the validation messages.
  397. foreach ($results as $result) {
  398. if (JError::isError($result) && $result->get('level') === E_WARNING) {
  399. $this->setError($result);
  400. $return = false;
  401. }
  402. }
  403. }
  404. }
  405. }
  406. return $return;
  407. }
  408. /**
  409. * Method to add a field to a group.
  410. *
  411. * @param object $field The field object to add.
  412. * @param string $group The group to add the field to.
  413. * @return void
  414. */
  415. public function addField(&$field, $group = '_default')
  416. {
  417. // Add the field to the group.
  418. $this->_groups[$group][$field->attributes('name')] = $field;
  419. }
  420. /**
  421. * Method to add an array of fields to a group.
  422. *
  423. * @param array $fields An array of field objects to add.
  424. * @param string $group The group to add the fields to.
  425. * @return void
  426. */
  427. public function addFields(&$fields, $group = '_default')
  428. {
  429. // Add the fields to the group.
  430. foreach ($fields as $field) {
  431. $this->_groups[$group][$field->attributes('name')] = $field;
  432. }
  433. }
  434. /**
  435. * Method to get a form field.
  436. *
  437. * @param string $name The name of the form field.
  438. * @param string $group The group the field is in.
  439. * @param mixed $formControl The optional form control. Set to false to disable.
  440. * @param mixed $groupControl The optional group control. Set to false to disable.
  441. * @param mixed $value The optional value to render as the default for the field.
  442. * @return object Rendered Form Field object
  443. */
  444. public function getField($name, $group = '_default', $formControl = '_default', $groupControl = '_default', $value = null)
  445. {
  446. // Get the XML node.
  447. $node = isset($this->_groups[$group][$name]) ? $this->_groups[$group][$name] : null;
  448. // If there is no XML node for the given field name, return false.
  449. if (empty($node)) {
  450. return false;
  451. }
  452. // Load the field type.
  453. $type = $node->attributes('type');
  454. $field = & $this->loadFieldType($type);
  455. // If the field could not be loaded, get a text field.
  456. if ($field === false) {
  457. $field = & $this->loadFieldType('text');
  458. }
  459. // Get the value for the form field.
  460. if ($value === null) {
  461. $value = (array_key_exists($name, $this->_data[$group]) && ($this->_data[$group][$name] !== null)) ? $this->_data[$group][$name] : $node->attributes('default');
  462. }
  463. // Check the form control.
  464. if ($formControl == '_default' && $this->_options['array'] == false) {
  465. $formControl = false;
  466. } elseif ($formControl == '_default' && $this->_options['array'] == true) {
  467. $formControl = $this->_options['array'];
  468. }
  469. // Check the group control.
  470. if ($groupControl == '_default' && $this->_fieldsets[$group]['array'] == false) {
  471. $groupControl = false;
  472. } elseif ($groupControl == '_default' && $group !== '_default' && $this->_fieldsets[$group]['array'] == true) {
  473. $groupControl = $group;
  474. } elseif ($groupControl == '_default' && $group !== '_default' && is_string($this->_fieldsets[$group]['array']) && strlen($this->_fieldsets[$group]['array'])) {
  475. $groupControl = $this->_fieldsets[$group]['array'];
  476. }
  477. // Render the field.
  478. return $field->render($node, $value, $formControl, $groupControl);
  479. }
  480. /**
  481. * Method to get a field attribute value.
  482. *
  483. * @param string $field The name of the field.
  484. * @param string $attribute The name of the attribute.
  485. * @param mixed $default The default value of the attribute.
  486. * @param string $group The optional group of the field.
  487. * @return mixed The value of the attribute if set, otherwise the default value.
  488. */
  489. public function getFieldAttribute($field, $attribute, $default, $group = '_default')
  490. {
  491. $return = null;
  492. // Get the field attribute if it exists.
  493. if (isset($this->_groups[$group][$field])) {
  494. $return = $this->_groups[$group][$field]->attributes($attribute);
  495. }
  496. return $return !== null ? $return : $default;
  497. }
  498. /**
  499. * Method to replace a field in a group.
  500. *
  501. * @param object $field The field object to replace.
  502. * @param string $group The group to replace the field in.
  503. * @return boolean True on success, false when field does not exist.
  504. */
  505. public function setField(&$field, $group = '_default')
  506. {
  507. $return = false;
  508. // Add the fields to the group if it exists.
  509. if (isset($this->_groups[$group][$field->attributes('name')])) {
  510. $this->_groups[$group][$field->attributes('name')] = $field;
  511. $return = true;
  512. }
  513. return $return;
  514. }
  515. /**
  516. * Method to remove a field from a group.
  517. *
  518. * @param string $field The field to remove.
  519. * @param string $group The group to remove.
  520. * @return void
  521. */
  522. public function removeField($field, $group = '_default')
  523. {
  524. unset($this->_groups[$group][$field]);
  525. }
  526. /**
  527. * Method to set a field attribute value.
  528. *
  529. * @param string $field The name of the field.
  530. * @param string $attribute The name of the attribute.
  531. * @param mixed $value The value to set the attribute to.
  532. * @param string $group The optional group of the field.
  533. * @return boolean True on success, false when field does not exist.
  534. */
  535. public function setFieldAttribute($field, $attribute, $value, $group = '_default')
  536. {
  537. $return = false;
  538. // Set the field attribute if it exists.
  539. if (isset($this->_groups[$group][$field])) {
  540. $this->_groups[$group][$field]->addAttribute($attribute, $value);
  541. $return = true;
  542. }
  543. return $return;
  544. }
  545. /**
  546. * Method to get the fields in a group.
  547. *
  548. * @param string $group The form field group.
  549. * @param mixed $formControl The optional form control. Set to false to disable.
  550. * @param mixed $groupControl The optional group control. Set to false to disable.
  551. * @return array Associative array of rendered Form Field object by field name
  552. */
  553. public function getFields($group = '_default', $formControl = '_default', $groupControl = '_default')
  554. {
  555. $results = array();
  556. // Check the form control.
  557. if ($formControl == '_default' && $this->_options['array'] == false) {
  558. $formControl = false;
  559. } elseif ($formControl == '_default' && $this->_options['array'] == true) {
  560. $formControl = $this->_options['array'];
  561. }
  562. // Check the group control.
  563. if ($groupControl == '_default' && (empty($this->_fieldsets[$group]) || $this->_fieldsets[$group]['array'] == false)) {
  564. $groupControl = false;
  565. } elseif ($groupControl == '_default' && $group !== '_default' && isset($this->_fieldsets[$group]) && $this->_fieldsets[$group]['array'] == true) {
  566. $groupControl = $group;
  567. } elseif ($groupControl == '_default' && $group !== '_default' && isset($this->_fieldsets[$group]) && is_string($this->_fieldsets[$group]['array']) && strlen($this->_fieldsets[$group]['array'])) {
  568. $groupControl = $this->_fieldsets[$group]['array'];
  569. }
  570. // Check if the group exists.
  571. if (isset($this->_groups[$group])) {
  572. // Get the fields in the group.
  573. foreach ($this->_groups[$group] as $name => $node) {
  574. // Get the field info.
  575. $type = $node->attributes('type');
  576. $value = (isset($this->_data[$group]) && array_key_exists($name, $this->_data[$group]) && ($this->_data[$group][$name] !== null)) ? $this->_data[$group][$name] : $node->attributes('default');
  577. // Load the field.
  578. $field = &$this->loadFieldType($type);
  579. // If the field could not be loaded, get a text field.
  580. if ($field === false) {
  581. $field = &$this->loadFieldType('text');
  582. }
  583. // Render the field.
  584. $results[$name] = $field->render($node, $value, $formControl, $groupControl);
  585. }
  586. }
  587. return $results;
  588. }
  589. /**
  590. * Method to assign an array of fields to a group.
  591. *
  592. * @param array $fields An array of field objects to assign.
  593. * @param string $group The group to assign the fields to.
  594. * @return void
  595. */
  596. public function setFields(&$fields, $group = '_default')
  597. {
  598. // Reset the fields group,
  599. $this->_groups[$group] = array();
  600. // Add the fields to the group.
  601. foreach ($fields as $field) {
  602. $this->_groups[$group][$field->attributes('name')] = $field;
  603. }
  604. }
  605. public function getFieldsets()
  606. {
  607. return $this->_fieldsets;
  608. }
  609. /**
  610. * Method to get a list of groups.
  611. *
  612. * @return array An array of groups.
  613. */
  614. public function getGroups()
  615. {
  616. return array_keys($this->_groups);
  617. }
  618. /**
  619. * Method to remove a group.
  620. *
  621. * @param string $group The group to remove.
  622. * @return void
  623. */
  624. public function removeGroup($group)
  625. {
  626. unset($this->_groups[$group]);
  627. }
  628. /**
  629. * Method to get the input control for a field.
  630. *
  631. * @param string $name The field name.
  632. * @param string $group The group the field is in.
  633. * @param mixed $formControl The optional form control. Set to false to disable.
  634. * @param mixed $groupControl The optional group control. Set to false to disable.
  635. * @param mixed $value The optional value to render as the default for the field.
  636. * @return string The form field input control.
  637. */
  638. public function getInput($name, $group = '_default', $formControl = '_default', $groupControl = '_default', $value = null)
  639. {
  640. // Render the field input.
  641. $field = $this->getField($name, $group, $formControl, $groupControl, $value);
  642. $input = $field->input;
  643. return $input;
  644. }
  645. /**
  646. * Method to get the label for a field.
  647. *
  648. * @param string $name The field name.
  649. * @param string $group The group the field is in.
  650. * @param mixed $formControl The optional form control. Set to false to disable.
  651. * @param mixed $groupControl The optional group control. Set to false to disable.
  652. * @param mixed $value The optional value to render as the default for the field.
  653. * @return string The form field label.
  654. */
  655. public function getLabel($name, $group = '_default', $formControl = '_default', $groupControl = '_default', $value = null)
  656. {
  657. // Render the field label.
  658. $field = $this->getField($name, $group, $formControl, $groupControl, $value);
  659. $label = $field->label;
  660. return $label;
  661. }
  662. /**
  663. * Method to get the value of a field.
  664. *
  665. * @param string $field The field to set.
  666. * @param mixed $default The default value of the field if empty.
  667. * @param string $group The group the field is in.
  668. * @return boolean The value of the field or the default value if empty.
  669. */
  670. public function getValue($field, $default = null, $group = '_default')
  671. {
  672. $return = null;
  673. // Get the field value if it exists.
  674. if (isset($this->_groups[$group][$field]) && is_object($this->_groups[$group][$field])) {
  675. $return = array_key_exists($field, $this->_data[$group]) ? $this->_data[$group][$field] : $default;
  676. }
  677. return $return;
  678. }
  679. /**
  680. * Method to set the value of a field.
  681. *
  682. * @param string $field The field to set.
  683. * @param mixed $value The value to set the field to.
  684. * @param string $group The group the field is in.
  685. * @return boolean True if field exists, false otherwise.
  686. */
  687. public function setValue($field, $value, $group = '_default')
  688. {
  689. // Set the field if it exists.
  690. if (isset($this->_groups[$group][$field]) && is_object($this->_groups[$group][$field])) {
  691. $this->_data[$group][$field] = $value;
  692. return true;
  693. } else {
  694. return false;
  695. }
  696. }
  697. /**
  698. * Loads form fields from an XML fields element optionally reseting fields before loading new ones.
  699. *
  700. * @param object $xml The XML fields object.
  701. * @param boolean $reset Flag to toggle whether the form groups should be reset.
  702. * @return boolean True on success, false otherwise.
  703. */
  704. public function loadFieldsXML(&$xml, $reset = true)
  705. {
  706. // Check for an XML object.
  707. if (!is_object($xml)) {
  708. return false;
  709. }
  710. // Get the group name.
  711. $group = ($xml->attributes('group')) ? $xml->attributes('group') : '_default';
  712. if ($reset) {
  713. // Reset the field group.
  714. $this->setFields($xml->children(), $group);
  715. } else {
  716. // Add to the field group.
  717. $this->addFields($xml->children(), $group);
  718. }
  719. // Initialize the data group.
  720. if ($reset) {
  721. $this->_data[$group] = array();
  722. } else {
  723. if (!isset($this->_data[$group])) {
  724. $this->_data[$group] = array();
  725. }
  726. }
  727. // Get the fieldset attributes.
  728. $this->_fieldsets[$group] = array();
  729. // Get the fieldset label.
  730. if ($value = $xml->attributes('label')) {
  731. $this->_fieldsets[$group]['label'] = $value;
  732. }
  733. // Get the fieldset description.
  734. if ($value = $xml->attributes('description')) {
  735. $this->_fieldsets[$group]['description'] = $value;
  736. }
  737. // Get an optional hidden setting (at the discretion of the renderer to honour).
  738. if ($value = $xml->attributes('hidden')) {
  739. $this->_fieldsets[$group]['hidden'] = ($value == 'true' || $value == 1) ? true : false;
  740. }
  741. // Get the fieldset array option.
  742. switch ($xml->attributes('array'))
  743. {
  744. case 'true':
  745. $this->_fieldsets[$group]['array'] = true;
  746. break;
  747. case 'false':
  748. case '':
  749. $this->_fieldsets[$group]['array'] = false;
  750. break;
  751. default:
  752. $this->_fieldsets[$group]['array'] = $xml->attributes('array');
  753. break;
  754. }
  755. // Check if there is a field path to handle.
  756. if ($xml->attributes('addfieldpath'))
  757. {
  758. jimport('joomla.filesystem.folder');
  759. jimport('joomla.filesystem.path');
  760. $path = JPath::clean(JPATH_ROOT.'/'.$xml->attributes('addfieldpath'));
  761. // Add the field path to the list if it exists.
  762. if (JFolder::exists($path)) {
  763. JForm::addFieldPath($path);
  764. }
  765. }
  766. return true;
  767. }
  768. /**
  769. * Method to load a form field object.
  770. *
  771. * @param string $type The field type.
  772. * @param boolean $new Flag to toggle whether we should get a new instance of the object.
  773. * @return mixed Field object on success, false otherwise.
  774. */
  775. public function &loadFieldType($type, $new = true)
  776. {
  777. $false = false;
  778. $key = md5($type);
  779. $class = 'JFormField'.ucfirst($type);
  780. // Return the field object if it already exists and we don't need a new one.
  781. if (isset($this->_fieldTypes[$key]) && $new === false) {
  782. return $this->_fieldTypes[$key];
  783. }
  784. if (!class_exists('JFormField')) {
  785. juimport('jxtended.form.formfield');
  786. }
  787. if (!class_exists('JFormFieldList')) {
  788. require_once dirname(__FILE__).'/fields/list.php';
  789. }
  790. if (!class_exists($class)) {
  791. $paths = self::addFieldPath();
  792. // If the type is complex, add the base type to the paths.
  793. if ($pos = strpos($type, '_')) {
  794. // Add the complex type prefix to the paths.
  795. for ($i = 0, $n = count($paths); $i < $n; $i++) {
  796. // Derive the new path.
  797. $path = $paths[$i].'/'.strtolower(substr($type, 0, $pos));
  798. // If the path does not exist, add it.
  799. if (!in_array($path, $paths)) {
  800. array_unshift($paths, $path);
  801. }
  802. }
  803. // Break off the end of the complex type.
  804. $type = substr($type, $pos+1);
  805. }
  806. // Try to find the field file.
  807. jimport('joomla.filesystem.path');
  808. if ($file = JPath::find($paths, strtolower($type).'.php')) {
  809. require_once $file;
  810. } else {
  811. return $false;
  812. }
  813. // Check once and for all if the class exists.
  814. if (!class_exists($class)) {
  815. return $false;
  816. }
  817. }
  818. // Instantiate a new field object.
  819. $this->_fieldTypes[$key] = new $class($this);
  820. return $this->_fieldTypes[$key];
  821. }
  822. /**
  823. * Method to add a path to the list of form include paths.
  824. *
  825. * @param mixed $new A path or array of paths to add.
  826. * @return array The list of paths that have been added.
  827. * @static
  828. */
  829. public static function addFormPath($new = null)
  830. {
  831. static $paths;
  832. if (!isset($paths)) {
  833. $paths = array(dirname(__FILE__).'/forms');
  834. }
  835. // Force path to an array.
  836. settype($new, 'array');
  837. // Add the new paths to the list if not already there.
  838. foreach ($new as $path) {
  839. if (!in_array($path, $paths)) {
  840. array_unshift($paths, trim($path));
  841. }
  842. }
  843. return $paths;
  844. }
  845. /**
  846. * Method to add a path to the list of field include paths.
  847. *
  848. * @param mixed $new A path or array of paths to add.
  849. * @return array The list of paths that have been added.
  850. * @static
  851. */
  852. public static function addFieldPath($new = null)
  853. {
  854. static $paths;
  855. if (!isset($paths)) {
  856. $paths = array(dirname(__FILE__).'/fields');
  857. }
  858. // Force path to an array.
  859. settype($new, 'array');
  860. // Add the new paths to the list if not already there.
  861. foreach ($new as $path) {
  862. if (!in_array($path, $paths)) {
  863. array_unshift($paths, trim($path));
  864. }
  865. }
  866. return $paths;
  867. }
  868. }