Your IP : 216.73.216.11


Current Path : /home/digilove/public_html/41423/
Upload File :
Current File : //home/digilove/public_html/41423/Form.php.tar

home/digilove/public_html/libraries/regularlabs/src/Form.php000064400000050201152346271630020271 0ustar00<?php
/**
 * @package         Regular Labs Library
 * @version         23.7.24631
 * 
 * @author          Peter van Westen <info@regularlabs.com>
 * @link            https://regularlabs.com
 * @copyright       Copyright © 2023 Regular Labs All Rights Reserved
 * @license         GNU General Public License version 2 or later
 */

namespace RegularLabs\Library;

defined('_JEXEC') or die;

use Joomla\CMS\HTML\HTMLHelper as JHtml;
use Joomla\CMS\Language\Text as JText;
use Joomla\CMS\Plugin\PluginHelper as JPluginHelper;
use RegularLabs\Library\ParametersNew as Parameters;

class Form
{
    public static function getAddToLoadAjaxListScript($field, $name, $value, $id, $attributes = [], $simple = false)
    {
        $attributes['field'] = $field;
        $attributes['name']  = $name;
        $attributes['value'] = $value;
        $attributes['id']    = $id;

        $url = 'index.php?option=com_ajax&plugin=regularlabs&format=raw'
            . '&' . Uri::createCompressedAttributes(json_encode($attributes));

        $remove_spinner = "$('#" . $id . "_spinner').remove();";
        $replace_field  = "$('#" . $id . "').replaceWith(data);";
        $init_chosen    = 'document.getElementById("' . $id . '") && document.getElementById("' . $id . '").nodeName == "SELECT" && $("#' . $id . '").chosen();';

        $success = $replace_field;

        if ($simple)
        {
            $success .= $init_chosen;
        }
        else
        {
            Document::script('regularlabs/multiselect.min.js');
            Document::stylesheet('regularlabs/multiselect.min.css');

            $success .= "if(data.indexOf('rl_multiselect') > -1)\{RegularLabsMultiSelect.init($('#" . $id . "'));\} else { " . $init_chosen . "}";
        }

//        $success .= "console.log('#" . $id . "');";
//        $success .= "console.log(data);";

        $error   = $remove_spinner;
        $success = "if(data)\{" . $success . "\}" . $remove_spinner;

        $script = "jQuery(document).ready(function() {"
            . "RegularLabsScripts.addToLoadAjaxList("
            . "'" . addslashes($url) . "',"
            . "'" . addslashes($success) . "',"
            . "'" . addslashes($error) . "'"
            . ")"
            . "});";

        return '<script>' . $script . '</script>';
    }

    public static function getOptionsCount($options)
    {
        $count = 0;

        foreach ($options as $option)
        {
            $count++;
            if ( ! empty($option->links))
            {
                $count += self::getOptionsCount($option->links);
            }
        }

        return $count;
    }

    /**
     * Prepare the string for a select form field item
     *
     * @param string $string
     * @param int    $published
     * @param string $type
     * @param int    $remove_first
     *
     * @return string
     */
    public static function prepareSelectItem($string, $published = 1, $type = '', $remove_first = 0)
    {
        if (empty($string))
        {
            return '';
        }

        $string = str_replace(['&nbsp;', '&#160;'], ' ', $string);
        $string = RegEx::replace('- ', '  ', $string);

        for ($i = 0; $remove_first > $i; $i++)
        {
            $string = RegEx::replace('^  ', '', $string, '');
        }

        if (RegEx::match('^( *)(.*)$', $string, $match, ''))
        {
            [$string, $pre, $name] = $match;

            $pre = str_replace('  ', ' ·  ', $pre);
            $pre = RegEx::replace('(( ·  )*) ·  ', '\1 »  ', $pre);
            $pre = str_replace('  ', ' &nbsp; ', $pre);

            $string = $pre . $name;
        }

        switch (true)
        {
            case ($type == 'separator'):
                $string = '[[:font-weight:normal;font-style:italic;color:grey;:]]' . $string;
                break;

            case ($published == -2):
                $string = '[[:font-style:italic;color:grey;:]]' . $string . ' [' . JText::_('JTRASHED') . ']';
                break;

            case ($published == 0):
                $string = '[[:font-style:italic;color:grey;:]]' . $string . ' [' . JText::_('JUNPUBLISHED') . ']';
                break;

            case ($published == 2):
                $string = '[[:font-style:italic;:]]' . $string . ' [' . JText::_('JARCHIVED') . ']';
                break;
        }

        return $string;
    }

    /**
     * Render a full select list
     *
     * @param array  $options
     * @param string $name
     * @param string $value
     * @param string $id
     * @param int    $size
     * @param bool   $multiple
     * @param bool   $simple
     * @param bool   $readonly
     * @param bool   $ignore_max_count
     *
     * @return string
     */
    public static function selectList(&$options, $name, $value, $id, $size = 0, $multiple = false, $simple = false, $readonly = false, $ignore_max_count = false)
    {
        if (empty($options))
        {
            return '<fieldset class="radio">' . JText::_('RL_NO_ITEMS_FOUND') . '</fieldset>';
        }

        if ( ! $multiple)
        {
            $simple = true;
        }

        $params = Parameters::getPlugin('regularlabs');

        $value = ArrayHelper::toArray($value);
        $value = ArrayHelper::clean($value);

        if (count($value) === 1 && strpos($value[0], ',') !== false)
        {
            $value = ArrayHelper::toArray($value[0]);
        }

        $count = 0;
        if ($options != -1)
        {
            foreach ($options as $option)
            {
                $count++;
                if (isset($option->links))
                {
                    $count += count($option->links);
                }
                if ( ! $ignore_max_count && $count > $params->max_list_count)
                {
                    break;
                }
            }
        }

        if ($options == -1 || ( ! $ignore_max_count && $count > $params->max_list_count))
        {
            if (is_array($value))
            {
                $value = implode(',', $value);
            }
            if ( ! $value)
            {
                $input = '<textarea name="' . $name . '" id="' . $id . '" cols="40" rows="5">' . $value . '</textarea>';
            }
            else
            {
                $input = '<input type="text" name="' . $name . '" id="' . $id . '" value="' . $value . '" size="60">';
            }

            $plugin = JPluginHelper::getPlugin('system', 'regularlabs');

            $url = ! empty($plugin->id)
                ? 'index.php?option=com_plugins&task=plugin.edit&extension_id=' . $plugin->id
                : 'index.php?option=com_plugins&filter_folder=&filter_search=Regular%20Labs%20Library';

            $label   = JText::_('RL_ITEM_IDS');
            $text    = JText::_('RL_MAX_LIST_COUNT_INCREASE');
            $tooltip = JText::_('RL_MAX_LIST_COUNT_INCREASE_DESC,' . $params->max_list_count . ',RL_MAX_LIST_COUNT');
            $link    = '<a href="' . $url . '" target="_blank" id="' . $id . '_msg"'
                . ' class="hasPopover" title="' . $text . '" data-content="' . htmlentities($tooltip) . '">'
                . '<span class="icon icon-cog"></span>'
                . $text
                . '</a>';

            $script = 'jQuery("#' . $id . '_msg").popover({"html": true,"trigger": "hover focus","container": "body"})';

            return '<fieldset class="radio">'
                . '<label for="' . $id . '">' . $label . ':</label>'
                . $input
                . '<br><small>' . $link . '</small>'
                . '</fieldset>'
                . '<script>' . $script . '</script>';
        }

        if ($simple)
        {
            $first_level = $options[0]->level ?? 0;
            foreach ($options as &$option)
            {
                if ( ! isset($option->level))
                {
                    continue;
                }
                $repeat = ($option->level - $first_level > 0) ? $option->level - $first_level : 0;
                if ( ! $repeat)
                {
                    continue;
                }
                //$option->text = str_repeat(' - ', $repeat) . $option->text;
                $option->text = '[[:padding-left: ' . (5 + ($repeat * 15)) . 'px;:]]' . $option->text;
            }
        }

        if ( ! $multiple)
        {
            $attr = 'class="inputbox"';
            if ($readonly)
            {
                $attr .= ' readonly="readonly"';
            }

            if (is_array(reset($options)) && isset(reset($options)['items']))
            {
                return JHtml::_(
                    'select.groupedlist', $options, $name,
                    [
                        'id'          => $id,
                        'group.id'    => 'id',
                        'list.attr'   => $attr,
                        'list.select' => $value,
                    ]
                );
            }

            $html = JHtml::_('select.genericlist', $options, $name, $attr, 'value', 'text', $value, $id);

            return self::handlePreparedStyles($html);
        }

        $size = (int) $size ?: 300;

        if ($simple)
        {
            $attr = 'style="width: ' . $size . 'px" multiple="multiple"';
            if ($readonly)
            {
                $attr .= ' readonly="readonly"';
            }

            if (substr($name, -2) !== '[]')
            {
                $name .= '[]';
            }

            if (is_array(reset($options)) && isset(reset($options)['items']))
            {
                return JHtml::_(
                    'select.groupedlist', $options, $name,
                    [
                        'id'          => $id,
                        'group.id'    => 'id',
                        'list.attr'   => trim($attr),
                        'list.select' => $value,
                    ]
                );
            }

            $html = JHtml::_('select.genericlist', $options, $name, trim($attr), 'value', 'text', $value, $id);

            return self::handlePreparedStyles($html);
        }

        Language::load('com_modules', JPATH_ADMINISTRATOR);

        Document::script('regularlabs/multiselect.min.js');
        Document::stylesheet('regularlabs/multiselect.min.css');

        $count_total    = self::getOptionsCount($options);
        $count_selected = count($value);
        $has_nested     = $count_total > count($options);

        $html = [];

        $html[] = '<div class="well well-small rl_multiselect" id="' . $id . '">';
        $html[] = '<div class="form-inline rl_multiselect-controls">';
        $html[] = '<span class="small">' . JText::_('JSELECT') . ':
                    <a class="rl_multiselect-checkall" href="javascript:;">' . JText::_('JALL') . '</a>
                    <span class="ghosted">[' . $count_total . ']</span>,
                    <a class="rl_multiselect-uncheckall" href="javascript:;">' . JText::_('JNONE') . '</a>,
                    <a class="rl_multiselect-toggleall" href="javascript:;">' . JText::_('RL_TOGGLE') . '</a>
                </span>';
        $html[] = '<span> | </span>';
        if ($has_nested)
        {
            $html[] = '<span class="small">' . JText::_('RL_EXPAND') . ':
                    <a class="rl_multiselect-expandall" href="javascript:;">' . JText::_('JALL') . '</a>,
                    <a class="rl_multiselect-collapseall" href="javascript:;">' . JText::_('JNONE') . '</a>
                </span>';
            $html[] = '<span> | </span>';
        }
        $html[] = '<span class="small">' . JText::_('JSHOW') . ':
                    <a class="rl_multiselect-showall" href="javascript:;">' . JText::_('JALL') . '</a>
                    <span class="ghosted">[' . $count_total . ']</span>,
                        <a class="rl_multiselect-showselected" href="javascript:;">' . JText::_('RL_SELECTED') . '</a>
                    <span class="ghosted">[<span class="rl_multiselect-count-selected">' . $count_selected . '</span>]</span>
                </span>';
        $html[] = '<span class="rl_multiselect-maxmin">
                    <span> | </span>
                    <span class="small">
                        <a class="rl_multiselect-maximize" href="javascript:;">' . JText::_('RL_MAXIMIZE') . '</a>
                        <a class="rl_multiselect-minimize" style="display:none;" href="javascript:;">' . JText::_('RL_MINIMIZE') . '</a>
                    </span>
                </span>';
        $html[] = '<input type="text" name="rl_multiselect-filter" class="rl_multiselect-filter input-medium search-query pull-right" size="16"
                    autocomplete="off" placeholder="' . JText::_('JSEARCH_FILTER') . '" aria-invalid="false" tabindex="-1">';
        $html[] = '</div>';

        $html[] = '<hr class="hr-condensed">';

        $o = [];
        foreach ($options as $option)
        {
            $option->level ??= 0;
            $o[]           = $option;
            if (isset($option->links))
            {
                foreach ($option->links as $link)
                {
                    $link->level = $option->level + ($link->level ?? 1);
                    $o[]         = $link;
                }
            }
        }

        $html[]    = '<ul class="rl_multiselect-ul" style="max-height:300px;min-width:' . $size . 'px;overflow-x: hidden;">';
        $prevlevel = 0;

        foreach ($o as $i => $option)
        {
            if ($prevlevel < $option->level)
            {
                // correct wrong level indentations
                $option->level = $prevlevel + 1;

                $html[] = '<ul class="rl_multiselect-sub">';
            }
            else if ($prevlevel > $option->level)
            {
                $html[] = str_repeat('</li></ul>', $prevlevel - $option->level);
            }
            else if ($i)
            {
                $html[] = '</li>';
            }

            $labelclass = trim('pull-left ' . ($option->labelclass ?? ''));

            $html[] = '<li>';

            $item = '<div class="' . trim('rl_multiselect-item pull-left ' . ($option->class ?? '')) . '">';
            if (isset($option->title))
            {
                $labelclass .= ' nav-header';
            }

            if (isset($option->title) && ( ! isset($option->value) || ! $option->value))
            {
                $item .= '<label class="' . $labelclass . '">' . $option->title . '</label>';
            }
            else
            {
                $selected = in_array($option->value, $value) ? ' checked="checked"' : '';
                $disabled = (isset($option->disable) && $option->disable) ? ' disabled="disabled"' : '';

                if (empty($option->hide_select))
                {
                    $item .= '<input type="checkbox" class="pull-left" name="' . $name . '" id="' . $id . $option->value . '" value="' . $option->value . '"' . $selected . $disabled . '>';
                }

                $item .= '<label for="' . $id . $option->value . '" class="' . $labelclass . '">' . $option->text . '</label>';
            }
            $item   .= '</div>';
            $html[] = $item;

            if ( ! isset($o[$i + 1]) && $option->level > 0)
            {
                $html[] = str_repeat('</li></ul>', (int) $option->level);
            }
            $prevlevel = $option->level;
        }
        $html[] = '</ul>';
        $html[] = '
            <div style="display:none;" class="rl_multiselect-menu-block">
                <div class="pull-left nav-hover rl_multiselect-menu">
                    <div class="btn-group">
                        <a href="#" data-toggle="dropdown" class="dropdown-toggle btn btn-micro">
                            <span class="caret"></span>
                        </a>
                        <ul class="dropdown-menu">
                            <li class="nav-header">' . JText::_('COM_MODULES_SUBITEMS') . '</li>
                            <li class="divider"></li>
                            <li class=""><a class="checkall" href="javascript:;"><span class="icon-checkbox"></span> ' . JText::_('JSELECT') . '</a>
                            </li>
                            <li><a class="uncheckall" href="javascript:;"><span class="icon-checkbox-unchecked"></span> ' . JText::_('COM_MODULES_DESELECT') . '</a>
                            </li>
                            <div class="rl_multiselect-menu-expand">
                                <li class="divider"></li>
                                <li><a class="expandall" href="javascript:;"><span class="icon-plus"></span> ' . JText::_('RL_EXPAND') . '</a></li>
                                <li><a class="collapseall" href="javascript:;"><span class="icon-minus"></span> ' . JText::_('RL_COLLAPSE') . '</a></li>
                            </div>
                        </ul>
                    </div>
                </div>
            </div>';
        $html[] = '</div>';

        $html = implode('', $html);

        return self::handlePreparedStyles($html);
    }

    /**
     * Render a select list loaded via Ajax
     *
     * @param string $field
     * @param string $name
     * @param string $value
     * @param string $id
     * @param array  $attributes
     * @param bool   $simple
     *
     * @return string
     */
    public static function selectListAjax($field, $name, $value, $id, $attributes = [], $simple = false)
    {
        JHtml::_('jquery.framework');

        $script = self::getAddToLoadAjaxListScript($field, $name, $value, $id, $attributes, $simple);

        if (is_array($value))
        {
            $value = implode(',', $value);
        }

        Document::script('regularlabs/script.min.js');
        Document::stylesheet('regularlabs/style.min.css');

        $input = '<textarea name="' . $name . '" id="' . $id . '" cols="40" rows="5">' . $value . '</textarea>'
            . '<div id="' . $id . '_spinner" class="rl_spinner"></div>';

        return $input . $script;
    }

    /**
     * Render a simple select list
     *
     * @param array  $options
     * @param        $string $name
     * @param string $value
     * @param string $id
     * @param int    $size
     * @param bool   $multiple
     * @param bool   $readonly
     * @param bool   $ignore_max_count
     *
     * @return string
     */
    public static function selectListSimple(&$options, $name, $value, $id, $size = 0, $multiple = false, $readonly = false, $ignore_max_count = false)
    {
        return self::selectlist($options, $name, $value, $id, $size, $multiple, true, $readonly, $ignore_max_count);
    }

    /**
     * Render a simple select list loaded via Ajax
     *
     * @param string $field
     * @param string $name
     * @param string $value
     * @param string $id
     * @param array  $attributes
     *
     * @return string
     */
    public static function selectListSimpleAjax($field, $name, $value, $id, $attributes = [])
    {
        return self::selectListAjax($field, $name, $value, $id, $attributes, true);
    }

    /**
     * Replace style placeholders with actual style attributes
     *
     * @param string $string
     *
     * @return string
     */
    private static function handlePreparedStyles($string)
    {
        // No placeholders found
        if (strpos($string, '[[:') === false)
        {
            return $string;
        }

        // Doing following replacement in 3 steps to prevent the Regular Expressions engine from exploding

        // Replace style tags right after the html tags
        $string = RegEx::replace(
            ';?:\]\]\s*\[\[:',
            ';',
            $string
        );
        $string = RegEx::replace(
            '>\s*\[\[\:(.*?)\:\]\]',
            ' style="\1">',
            $string
        );

        // No more placeholders found
        if (strpos($string, '[[:') === false)
        {
            return $string;
        }

        // Replace style tags prepended with a minus and any amount of whitespace: '- '
        $string = RegEx::replace(
            '>((?:-\s*)+)\[\[\:(.*?)\:\]\]',
            ' style="\2">\1',
            $string
        );

        // No more placeholders found
        if (strpos($string, '[[:') === false)
        {
            return $string;
        }

        // Replace style tags prepended with whitespace, a minus and any amount of whitespace: ' - '
        $string = RegEx::replace(
            '>((?:\s+-\s*)+)\[\[\:(.*?)\:\]\]',
            ' style="\2">\1',
            $string
        );

        return $string;
    }
}
home/digilove/public_html/110/libraries/fof30/Form/Form.php000064400000071360152355243650017332 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Form;

use FOF30\Container\Container;
use FOF30\Form\Header\HeaderBase;
use FOF30\Model\DataModel;
use FOF30\View\DataView\DataViewInterface;
use JFactory;
use JForm;
use Joomla\Registry\Registry;
use JText;
use SimpleXMLElement;

defined('_JEXEC') or die;

/**
 * Form is an extension to JForm which support not only edit views but also
 * browse (record list) and read (single record display) views based on XML
 * forms.
 *
 * @package  FrameworkOnFramework
 * @since    2.0
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class Form extends JForm
{
	/**
	 * The model attached to this view
	 *
	 * @var DataModel
	 */
	protected $model;

	/**
	 * The view used to render this form
	 *
	 * @var DataViewInterface
	 */
	protected $view;

	/**
	 * The Container this form belongs to
	 *
	 * @var \FOF30\Container\Container
	 */
	protected $container;

	/**
	 * Map of entity objects for re-use.
	 * Prototypes for all fields and rules are here.
	 *
	 * Array's structure:
	 * <code>
	 * entities:
	 * {ENTITY_NAME}:
	 * {KEY}: {OBJECT}
	 * </code>
	 *
	 * @var    array
	 */
	protected $entities = array();

	/**
	 * Method to instantiate the form object.
	 *
	 * @param   Container $container The component Container where this form belongs to
	 * @param   string    $name      The name of the form.
	 * @param   array     $options   An array of form options.
	 */
	public function __construct(Container $container, $name, array $options = array())
	{
		parent::__construct($name, $options);

		$this->container = $container;
	}

	/**
	 * Returns the value of an attribute of the form itself
	 *
	 * @param   string $attribute The name of the attribute
	 * @param   mixed  $default   Optional default value to return
	 *
	 * @return  mixed
	 *
	 * @since 2.0
	 */
	public function getAttribute($attribute, $default = null)
	{
		$value = $this->xml->attributes()->$attribute;

		if (is_null($value))
		{
			return $default;
		}
		else
		{
			return (string)$value;
		}
	}

	/**
	 * Loads the CSS files defined in the form, based on its cssfiles attribute
	 *
	 * @return  void
	 *
	 * @since 2.0
	 */
	public function loadCSSFiles()
	{
		// Support for CSS files
		$cssfiles = $this->getAttribute('cssfiles');

		if (!empty($cssfiles))
		{
			$cssfiles = explode(',', $cssfiles);

			foreach ($cssfiles as $cssfile)
			{
				$this->getView()->addCssFile(trim($cssfile));
			}
		}

		// Support for LESS files
		$lessfiles = $this->getAttribute('lessfiles');

		if (!empty($lessfiles))
		{
			$lessfiles = explode(',', $lessfiles);

			foreach ($lessfiles as $def)
			{
				$parts = explode('||', $def, 2);
				$lessfile = $parts[0];
				$alt = (count($parts) > 1) ? trim($parts[1]) : null;
				$this->getView()->addLess(trim($lessfile), $alt);
			}
		}
	}

	/**
	 * Loads the Javascript files defined in the form, based on its jsfiles attribute
	 *
	 * @return  void
	 *
	 * @since 2.0
	 */
	public function loadJSFiles()
	{
		$jsfiles = $this->getAttribute('jsfiles');

		if (empty($jsfiles))
		{
			return;
		}

		$jsfiles = explode(',', $jsfiles);

		foreach ($jsfiles as $jsfile)
		{
			$this->getView()->addJavascriptFile(trim($jsfile));
		}
	}

	/**
	 * Returns a reference to the protected $data object, allowing direct
	 * access to and manipulation of the form's data.
	 *
	 * @return   \JRegistry|Registry  The form's data registry
	 *
	 * @since 2.0
	 */
	public function &getData()
	{
		return $this->data;
	}

	/**
	 * Method to load the form description from an XML file.
	 *
	 * The reset option works on a group basis. If the XML file references
	 * groups that have already been created they will be replaced with the
	 * fields in the new XML file unless the $reset parameter has been set
	 * to false.
	 *
	 * @param   string  $file   The filesystem path of an XML file.
	 * @param   bool    $reset  Flag to toggle whether form fields should be replaced if a field
	 *                          already exists with the same group/name.
	 * @param   bool    $xpath  An optional xpath to search for the fields.
	 *
	 * @return  boolean  True on success, false otherwise.
	 */
	public function loadFile($file, $reset = true, $xpath = false)
	{
		// Check to see if the path is an absolute path.
		if (!is_file($file))
		{
			return false;
		}

		// Attempt to load the XML file.
		$xml = simplexml_load_file($file);

		return $this->load($xml, $reset, $xpath);
	}

	/**
	 * Attaches a DataModel to this form
	 *
	 * @param   DataModel &$model The model to attach to the form
	 *
	 * @return  void
	 */
	public function setModel(DataModel &$model)
	{
		$this->model = $model;
	}

	/**
	 * Returns the DataModel attached to this form
	 *
	 * @return DataModel
	 */
	public function &getModel()
	{
		return $this->model;
	}

	/**
	 * Attaches a DataViewInterface to this form
	 *
	 * @param   DataViewInterface &$view The view to attach to the form
	 *
	 * @return  void
	 */
	public function setView(DataViewInterface &$view)
	{
		$this->view = $view;
	}

	/**
	 * Returns the DataViewInterface attached to this form
	 *
	 * @return DataViewInterface
	 */
	public function &getView()
	{
		return $this->view;
	}

	/**
	 * Method to get an array of FormHeader objects in the headerset.
	 *
	 * @return  array  The array of HeaderInterface objects in the headerset.
	 *
	 * @since   2.0
	 */
	public function getHeaderset()
	{
		$fields = array();

		$elements = $this->findHeadersByGroup();

		// If no field elements were found return empty.

		if (empty($elements))
		{
			return $fields;
		}

		// Build the result array from the found field elements.

		/** @var \SimpleXMLElement $element */
		foreach ($elements as $element)
		{
			// Get the field groups for the element.
			$attrs = $element->xpath('ancestor::headerset[@name]/@name');
			$groups = array_map('strval', $attrs ? $attrs : array());
			$group = implode('.', $groups);

			// If the field is successfully loaded add it to the result array.
			/** @var HeaderBase $field */
			if ($field = $this->loadHeader($element, $group))
			{
				$fields[$field->id] = $field;
			}
		}

		return $fields;
	}

	/**
	 * Method to get an array of <header /> elements from the form XML document which are
	 * in a control group by name.
	 *
	 * @param   mixed   $group    The optional dot-separated form group path on which to find the fields.
	 *                            Null will return all fields. False will return fields not in a group.
	 * @param   boolean $nested   True to also include fields in nested groups that are inside of the
	 *                            group for which to find fields.
	 *
	 * @return  \SimpleXMLElement|bool  Boolean false on error or array of SimpleXMLElement objects.
	 *
	 * @since   2.0
	 */
	protected function &findHeadersByGroup($group = null, $nested = false)
	{
		$false = false;
		$fields = array();

		// Make sure there is a valid JForm XML document.
		if (!($this->xml instanceof \SimpleXMLElement))
		{
			return $false;
		}

		// Get only fields in a specific group?
		if ($group)
		{
			// Get the fields elements for a given group.
			$elements = &$this->findHeader($group);

			// Get all of the field elements for the fields elements.
			/** @var \SimpleXMLElement $element */
			foreach ($elements as $element)
			{
				// If there are field elements add them to the return result.
				if ($tmp = $element->xpath('descendant::header'))
				{
					// If we also want fields in nested groups then just merge the arrays.
					if ($nested)
					{
						$fields = array_merge($fields, $tmp);
					}

					// If we want to exclude nested groups then we need to check each field.
					else
					{
						$groupNames = explode('.', $group);

						foreach ($tmp as $field)
						{
							// Get the names of the groups that the field is in.
							$attrs = $field->xpath('ancestor::headers[@name]/@name');
							$names = array_map('strval', $attrs ? $attrs : array());

							// If the field is in the specific group then add it to the return list.
							if ($names == (array)$groupNames)
							{
								$fields = array_merge($fields, array($field));
							}
						}
					}
				}
			}
		}
		elseif ($group === false)
		{
			// Get only field elements not in a group.
			$fields = $this->xml->xpath('descendant::headers[not(@name)]/header | descendant::headers[not(@name)]/headerset/header ');
		}
		else
		{
			// Get an array of all the <header /> elements.
			$fields = $this->xml->xpath('//header');
		}

		return $fields;
	}

	/**
	 * Method to get a header field represented as a HeaderInterface object.
	 *
	 * @param   string $name  The name of the header field.
	 * @param   string $group The optional dot-separated form group path on which to find the field.
	 * @param   mixed  $value The optional value to use as the default for the field. (DEPRECATED)
	 *
	 * @return  HeaderInterface|bool  The HeaderInterface object for the field or boolean false on error.
	 *
	 * @since   2.0
	 */
	public function getHeader($name, $group = null, $value = null)
	{
		// Make sure there is a valid Form XML document.
		if (!($this->xml instanceof \SimpleXMLElement))
		{
			return false;
		}

		// Attempt to find the field by name and group.
		$element = $this->findHeader($name, $group);

		// If the field element was not found return false.
		if (!$element)
		{
			return false;
		}

		return $this->loadHeader($element, $group);
	}

	/**
	 * Method to get a header field represented as an XML element object.
	 *
	 * @param   string $name  The name of the form field.
	 * @param   string $group The optional dot-separated form group path on which to find the field.
	 *
	 * @return  mixed  The XML element object for the field or boolean false on error.
	 *
	 * @since   2.0
	 */
	protected function findHeader($name, $group = null)
	{
		$element = false;
		$fields = array();

		// Make sure there is a valid JForm XML document.
		if (!($this->xml instanceof \SimpleXMLElement))
		{
			return false;
		}

		// Let's get the appropriate field element based on the method arguments.
		if ($group)
		{
			// Get the fields elements for a given group.
			$elements = &$this->findGroup($group);

			// Get all of the field elements with the correct name for the fields elements.
			/** @var \SimpleXMLElement $element */
			foreach ($elements as $element)
			{
				// If there are matching field elements add them to the fields array.
				if ($tmp = $element->xpath('descendant::header[@name="' . $name . '"]'))
				{
					$fields = array_merge($fields, $tmp);
				}
			}

			// Make sure something was found.
			if (!$fields)
			{
				return false;
			}

			// Use the first correct match in the given group.
			$groupNames = explode('.', $group);

			/** @var \SimpleXMLElement $field */
			foreach ($fields as &$field)
			{
				// Get the group names as strings for ancestor fields elements.
				$attrs = $field->xpath('ancestor::headerfields[@name]/@name');
				$names = array_map('strval', $attrs ? $attrs : array());

				// If the field is in the exact group use it and break out of the loop.
				if ($names == (array)$groupNames)
				{
					$element = &$field;
					break;
				}
			}
		}
		else
		{
			// Get an array of fields with the correct name.
			$fields = $this->xml->xpath('//header[@name="' . $name . '"]');

			// Make sure something was found.
			if (!$fields)
			{
				return false;
			}

			// Search through the fields for the right one.
			foreach ($fields as &$field)
			{
				// If we find an ancestor fields element with a group name then it isn't what we want.
				if ($field->xpath('ancestor::headerfields[@name]'))
				{
					continue;
				}

				// Found it!
				else
				{
					$element = &$field;
					break;
				}
			}
		}

		return $element;
	}

	/**
	 * Method to load, setup and return a HeaderInterface object based on field data.
	 *
	 * @param   string $element The XML element object representation of the form field.
	 * @param   string $group   The optional dot-separated form group path on which to find the field.
	 *
	 * @return  HeaderInterface|bool  The HeaderInterface object for the field or boolean false on error.
	 *
	 * @since   2.0
	 */
	protected function loadHeader($element, $group = null)
	{
		// Make sure there is a valid SimpleXMLElement.
		if (!($element instanceof \SimpleXMLElement))
		{
			return false;
		}

		// Get the field type.
		$type = $element['type'] ? (string)$element['type'] : 'field';

		// Load the JFormField object for the field.
		$field = $this->loadHeaderType($type);

		// If the object could not be loaded, get a text field object.
		if ($field === false)
		{
			$field = $this->loadHeaderType('field');
		}

		// Setup the HeaderInterface object.
		$field->setForm($this);

		if ($field->setup($element, $group))
		{
			return $field;
		}
		else
		{
			return false;
		}
	}

	/**
	 * Method to remove a header from the form definition.
	 *
	 * @param   string  $name   The name of the form field for which remove.
	 * @param   string  $group  The optional dot-separated form group path on which to find the field.
	 *
	 * @return  boolean  True on success, false otherwise.
	 *
	 * @throws  \UnexpectedValueException
	 */
	public function removeHeader($name, $group = null)
	{
		// Make sure there is a valid JForm XML document.
		if (!($this->xml instanceof SimpleXMLElement))
		{
			throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this)));
		}

		// Find the form field element from the definition.
		$element = $this->findHeader($name, $group);

		// If the element exists remove it from the form definition.
		if ($element instanceof SimpleXMLElement)
		{
			$dom = dom_import_simplexml($element);
			$dom->parentNode->removeChild($dom);

			return true;
		}

		return false;
	}

	/**
	 * Proxy for {@link Helper::loadFieldType()}.
	 *
	 * @param   string  $type The field type.
	 * @param   boolean $new  Flag to toggle whether we should get a new instance of the object.
	 *
	 * @return  FieldInterface|bool  FieldInterface object on success, false otherwise.
	 *
	 * @since   2.0
	 */
	protected function loadFieldType($type, $new = true)
	{
		return $this->loadType('field', $type, $new);
	}

	/**
	 * Proxy for {@link Helper::loadHeaderType()}.
	 *
	 * @param   string  $type The field type.
	 * @param   boolean $new  Flag to toggle whether we should get a new instance of the object.
	 *
	 * @return  HeaderInterface|bool  HeaderInterface object on success, false otherwise.
	 *
	 * @since   2.0
	 */
	protected function loadHeaderType($type, $new = true)
	{
		return $this->loadType('header', $type, $new);
	}

	/**
	 * Proxy for {@link Helper::loadRuleType()}.
	 *
	 * @param   string  $type The rule type.
	 * @param   boolean $new  Flag to toggle whether we should get a new instance of the object.
	 *
	 * @return  \JFormRule|bool  JFormRule object on success, false otherwise.
	 *
	 * @see     Helper::loadRuleType()
	 * @since   2.0
	 */
	protected function loadRuleType($type, $new = true)
	{
		return $this->loadType('rule', $type, $new);
	}

	/**
	 * Method to load a form entity object given a type.
	 * Each type is loaded only once and then used as a prototype for other objects of same type.
	 * Please, use this method only with those entities which support types (forms don't support them).
	 *
	 * @param   string  $entity The entity.
	 * @param   string  $type   The entity type.
	 * @param   boolean $new    Flag to toggle whether we should get a new instance of the object.
	 *
	 * @return  mixed Entity object on success, false otherwise.
	 */
	protected function loadType($entity, $type, $new = true)
	{
		// Reference to an array with current entity's type instances
		$types = &$this->entities[$entity];

		// Return an entity object if it already exists and we don't need a new one.
		if (isset($types[$type]) && $new === false)
		{
			return $types[$type];
		}

		$class = $this->loadClass($entity, $type);

		if ($class !== false)
		{
			// Instantiate a new type object.
			$types[$type] = new $class;

			return $types[$type];
		}
		else
		{
			return false;
		}
	}

	/**
	 * Load a class for one of the form's entities of a particular type.
	 * Currently, it makes sense to use this method for the "field" and "rule" entities
	 * (but you can support more entities in your subclass).
	 *
	 * @param   string $entity One of the form entities (field, header or rule).
	 * @param   string $type   Type of an entity.
	 *
	 * @return  mixed  Class name on success or false otherwise.
	 *
	 * @since   2.0
	 */
	public function loadClass($entity, $type)
	{
		// Get the prefixes for namespaced classes (FOF3 way)
		$namespacedPrefixes = array(
			$this->container->getNamespacePrefix(),
			'FOF30\\',
		);

		// Get the prefixes for non-namespaced classes (FOF2 and Joomla! way)
		$plainPrefixes = array('J');

		// If the type is given as prefix.type add the custom type into the two prefix arrays
		if (strpos($type, '.'))
		{
			list($prefix, $type) = explode('.', $type);

			array_unshift($plainPrefixes, $prefix);
			array_unshift($namespacedPrefixes, $prefix);
		}

		// First try to find the namespaced class
		foreach ($namespacedPrefixes as $prefix)
		{
			$class = rtrim($prefix, '\\') . '\\Form\\' . ucfirst($entity) . '\\' . ucfirst($type);

			if (class_exists($class, true))
			{
				return $class;
			}
		}

		// TODO The rest of the code is legacy and will be removed in a future version

		// Then try to find the non-namespaced class
		$classes = array();

		foreach ($plainPrefixes as $prefix)
		{
			$class = \JString::ucfirst($prefix, '_') . 'Form' . \JString::ucfirst($entity, '_') . \JString::ucfirst($type, '_');

			if (class_exists($class, true))
			{
				return $class;
			}

			$classes[] = $class;
		}

		// Get the field search path array.
		$reflector = new \ReflectionClass('\\JFormHelper');
		$addPathMethod = $reflector->getMethod('addPath');
		$addPathMethod->setAccessible(true);
		$paths = $addPathMethod->invoke(null, $entity);

		// If the type is complex, add the base type to the paths.
		if ($pos = strpos($type, '_'))
		{
			// Add the complex type prefix to the paths.
			for ($i = 0, $n = count($paths); $i < $n; $i++)
			{
				// Derive the new path.
				$path = $paths[$i] . '/' . strtolower(substr($type, 0, $pos));

				// If the path does not exist, add it.
				if (!in_array($path, $paths))
				{
					$paths[] = $path;
				}
			}

			// Break off the end of the complex type.
			$type = substr($type, $pos + 1);
		}

		// Try to find the class file.
		$type = strtolower($type) . '.php';

		foreach ($paths as $path)
		{
			if ($file = \JPath::find($path, $type))
			{
				require_once $file;

				foreach ($classes as $class)
				{
					if (class_exists($class, false))
					{
						return $class;
					}
				}
			}
		}

		return false;
	}

	/**
	 * WARNING: THIS IS IGNORED IN FOF3!
	 *
	 * @param   string  $new  IGNORED!
	 *
	 * @return  void
	 *
	 * @deprecated 3.0
	 */
	public static function addFieldPath($new = null)
	{
		if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter...

		if (class_exists('JLog'))
		{
			\JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated');
		}
	}

	/**
	 * WARNING: THIS IS IGNORED IN FOF3!
	 *
	 * @param   string  $new  IGNORED!
	 *
	 * @return  void
	 *
	 * @deprecated 3.0
	 */
	public static function addHeaderPath($new = null)
	{
		if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter...

		if (class_exists('JLog'))
		{
			\JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated');
		}
	}

	/**
	 * WARNING: THIS IS IGNORED IN FOF3!
	 *
	 * @param   string  $new  IGNORED!
	 *
	 * @return  void
	 *
	 * @deprecated 3.0
	 */
	public static function addFormPath($new = null)
	{
		if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter...

		if (class_exists('JLog'))
		{
			\JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated');
		}
	}

	/**
	 * WARNING: THIS IS IGNORED IN FOF3!
	 *
	 * @param   string  $new  IGNORED!
	 *
	 * @return  void
	 *
	 * @deprecated 3.0
	 */
	public static function addRulePath($new = null)
	{
		if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter...

		if (class_exists('JLog'))
		{
			\JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated');
		}
	}

	/**
	 * Get a reference to the form's Container
	 *
	 * @return Container
	 */
	public function &getContainer()
	{
		return $this->container;
	}

	/**
	 * Set the form's Container
	 *
	 * @param Container $container
	 */
	public function setContainer($container)
	{
		$this->container = $container;
	}

	/**
	 * Method to bind data to the form.
	 *
	 * @param   mixed  $data  An array or object of data to bind to the form.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   11.1
	 */
	public function bind($data)
	{
		$this->data = class_exists('JRegistry') ? new \JRegistry() : new Registry();

		if (is_object($data) && ($data instanceof DataModel))
		{
			$maxDepth = (int) $this->getAttribute('relation_depth', '1');

			return parent::bind($this->modelToBindSource($data, $maxDepth));
		}

		return parent::bind($data);
	}

	/**
	 * Method to bind data to the form for the group level.
	 *
	 * @param   string  $group  The dot-separated form group path on which to bind the data.
	 * @param   mixed   $data   An array or object of data to bind to the form for the group level.
	 *
	 * @return  void
	 *
	 * @since   11.1
	 */
	protected function bindLevel($group, $data)
	{
		if (is_object($data) && ($data instanceof DataModel))
		{
			parent::bindLevel($group, $this->modelToBindSource($data));

			return;
		}

		parent::bindLevel($group, $data);
	}

	/**
	 * Method to load, setup and return a JFormField object based on field data.
	 *
	 * @param   string  $element  The XML element object representation of the form field.
	 * @param   string  $group    The optional dot-separated form group path on which to find the field.
	 * @param   mixed   $value    The optional value to use as the default for the field.
	 *
	 * @return  mixed  The JFormField object for the field or boolean false on error.
	 *
	 * @since   11.1
	 */
	protected function loadField($element, $group = null, $value = null)
	{
		// Make sure there is a valid SimpleXMLElement.
		if (!($element instanceof SimpleXMLElement))
		{
			return false;
		}

		// Get the field type.
		$type = $element['type'] ? (string) $element['type'] : 'text';

		// Load the JFormField object for the field.
		$field = $this->loadFieldType($type);

		// If the object could not be loaded, get a text field object.
		if ($field === false)
		{
			$field = $this->loadFieldType('text');
		}

		/*
		 * Get the value for the form field if not set.
		 * Default to the translated version of the 'default' attribute
		 * if 'translate_default' attribute if set to 'true' or '1'
		 * else the value of the 'default' attribute for the field.
		 */
		if ($value === null)
		{
			$default = (string) $element['default'];

			if (($translate = $element['translate_default']) && ((string) $translate == 'true' || (string) $translate == '1'))
			{
				$lang = JFactory::getLanguage();

				if ($lang->hasKey($default))
				{
					$debug = $lang->setDebug(false);
					$default = JText::_($default);
					$lang->setDebug($debug);
				}
				else
				{
					$default = JText::_($default);
				}
			}

			$getValueFrom = (isset($element['name_from'])) ? (string) $element['name_from'] : (string) $element['name'];

			$value = $this->getValue($getValueFrom, $group, $default);
		}

		// Setup the JFormField object.
		$field->setForm($this);

		if ($field->setup($element, $value, $group))
		{
			return $field;
		}
		else
		{
			return false;
		}
	}

	/**
	 * Method to get a form field represented as an XML element object.
	 *
	 * @param   string  $name   The name of the form field.
	 * @param   string  $group  The optional dot-separated form group path on which to find the field.
	 *
	 * @return  mixed  The XML element object for the field or boolean false on error.
	 *
	 * @since   11.1
	 */
	protected function findField($name, $group = null)
	{
		$element = false;
		$fields = array();

		// Make sure there is a valid JForm XML document.
		if (!($this->xml instanceof SimpleXMLElement))
		{
			return false;
		}

		// Let's get the appropriate field element based on the method arguments.
		if ($group)
		{
			// Get the fields elements for a given group.
			$elements = &$this->findGroup($group);

			// Get all of the field elements with the correct name for the fields elements.
			/** @var SimpleXMLElement $element */
			foreach ($elements as $element)
			{
				// If there are matching field elements add them to the fields array.
				if ($tmp = $element->xpath('descendant::field[@name="' . $name . '"]'))
				{
					$fields = array_merge($fields, $tmp);
				}
				elseif ($tmp = $element->xpath('descendant::field[@name_from="' . $name . '"]'))
				{
					$fields = array_merge($fields, $tmp);
				}
			}

			// Make sure something was found.
			if (!$fields)
			{
				return false;
			}

			// Use the first correct match in the given group.
			$groupNames = explode('.', $group);

			/** @var SimpleXMLElement $field */
			foreach ($fields as &$field)
			{
				// Get the group names as strings for ancestor fields elements.
				$attrs = $field->xpath('ancestor::fields[@name]/@name');
				$names = array_map('strval', $attrs ? $attrs : array());

				// If the field is in the exact group use it and break out of the loop.
				if ($names == (array) $groupNames)
				{
					$element = &$field;
					break;
				}
			}
		}
		else
		{
			// Get an array of fields with the correct name.
			$fields = $this->xml->xpath('//field[@name="' . $name . '"]');

			if (!$fields)
			{
				$fields = array();
			}

			$fieldsNameFrom = $this->xml->xpath('//field[@name_from="' . $name . '"]');

			if ($fieldsNameFrom)
			{
				$fields = array_merge($fields, $fieldsNameFrom);
			}

			// Make sure something was found.
			if (empty($fields))
			{
				return false;
			}

			// Search through the fields for the right one.
			foreach ($fields as &$field)
			{
				// If we find an ancestor fields element with a group name then it isn't what we want.
				if ($field->xpath('ancestor::fields[@name]'))
				{
					continue;
				}

				// Found it!
				else
				{
					$element = &$field;
					break;
				}
			}
		}

		return $element;
	}

	/**
	 * Converts a DataModel into data suitable for use with the form. The difference to the Model's getData() method is
	 * that we process hasOne and belongsTo relations. This is a recursive function which will be called at most
	 * $maxLevel deep. You can set this in the form XML file, in the relation_depth attribute.
	 *
	 * The $modelsProcessed array which is passed in successive recursions lets us prevent pointless Inception-style
	 * recursions, e.g. Model A is related to Model B is related to Model C is related to Model A. You clearly don't
	 * care to see a.b.c.a.b in the results. You just want a.b.c. Obviously c is indirectly related to a because that's
	 * where you began the recursion anyway.
	 *
	 * @param   DataModel  $model            The item to dump its contents into an array
	 * @param   int        $maxLevel         Maximum nesting level of relations to process. Default: 1.
	 * @param   array      $modelsProcessed  Array of the fully qualified model class names already processed.
	 *
	 * @return  array
	 * @throws  DataModel\Relation\Exception\RelationNotFound
	 */
	protected function modelToBindSource(DataModel $model, $maxLevel = 1, $modelsProcessed = array())
	{
		$maxLevel--;

		$data = $model->toArray();

		$relations = $model->getRelations()->getRelationNames();
		$relationTypes = $model->getRelations()->getRelationTypes();
		$relationTypes = array_map(function ($x) {
			return ltrim($x, '\\');
		}, $relationTypes);
		$relationTypes = array_flip($relationTypes);

		if (is_array($relations) && count($relations) && ($maxLevel >= 0))
		{
			foreach ($relations as $relationName)
			{
				$rel = $model->getRelations()->getRelation($relationName);
				$class = get_class($rel);

				if (!isset($relationTypes[$class]))
				{
					continue;
				}

				if (!in_array($relationTypes[$class], array('hasOne', 'belongsTo')))
				{
					continue;
				}

				/** @var DataModel $relData */
				$relData = $model->$relationName;

				if (!($relData instanceof DataModel))
				{
					continue;
				}

				$modelType = get_class($relData);

				if (in_array($modelType, $modelsProcessed))
				{
					continue;
				}

				$modelsProcessed[] = $modelType;

				$relDataArray = $this->modelToBindSource($relData, $maxLevel, $modelsProcessed);

				if (!is_array($relDataArray) || empty($relDataArray))
				{
					continue;
				}

				foreach ($relDataArray as $k => $v)
				{
					$data[$relationName . '.' . $k] = $v;
				}
			}
		}

		return $data;
	}


}