1<?php
2/**
3 * @package     Joomla.Platform
4 * @subpackage  Form
5 *
6 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
7 * @license     GNU General Public License version 2 or later; see LICENSE
8 */
9
10defined('JPATH_PLATFORM') or die;
11
12JFormHelper::loadFieldClass('list');
13
14/**
15 * Form Field class for the Joomla Platform.
16 * Displays options as a list of checkboxes.
17 * Multiselect may be forced to be true.
18 *
19 * @see    JFormFieldCheckbox
20 * @since  1.7.0
21 */
22class JFormFieldCheckboxes extends JFormFieldList
23{
24	/**
25	 * The form field type.
26	 *
27	 * @var    string
28	 * @since  1.7.0
29	 */
30	protected $type = 'Checkboxes';
31
32	/**
33	 * Name of the layout being used to render the field
34	 *
35	 * @var    string
36	 * @since  3.5
37	 */
38	protected $layout = 'joomla.form.field.checkboxes';
39
40	/**
41	 * Flag to tell the field to always be in multiple values mode.
42	 *
43	 * @var    boolean
44	 * @since  1.7.0
45	 */
46	protected $forceMultiple = true;
47
48	/**
49	 * The comma separated list of checked checkboxes value.
50	 *
51	 * @var    mixed
52	 * @since  3.2
53	 */
54	public $checkedOptions;
55
56	/**
57	 * Method to get certain otherwise inaccessible properties from the form field object.
58	 *
59	 * @param   string  $name  The property name for which to get the value.
60	 *
61	 * @return  mixed  The property value or null.
62	 *
63	 * @since   3.2
64	 */
65	public function __get($name)
66	{
67		switch ($name)
68		{
69			case 'forceMultiple':
70			case 'checkedOptions':
71				return $this->$name;
72		}
73
74		return parent::__get($name);
75	}
76
77	/**
78	 * Method to set certain otherwise inaccessible properties of the form field object.
79	 *
80	 * @param   string  $name   The property name for which to set the value.
81	 * @param   mixed   $value  The value of the property.
82	 *
83	 * @return  void
84	 *
85	 * @since   3.2
86	 */
87	public function __set($name, $value)
88	{
89		switch ($name)
90		{
91			case 'checkedOptions':
92				$this->checkedOptions = (string) $value;
93				break;
94
95			default:
96				parent::__set($name, $value);
97		}
98	}
99
100	/**
101	 * Method to get the radio button field input markup.
102	 *
103	 * @return  string  The field input markup.
104	 *
105	 * @since   1.7.0
106	 */
107	protected function getInput()
108	{
109		if (empty($this->layout))
110		{
111			throw new UnexpectedValueException(sprintf('%s has no layout assigned.', $this->name));
112		}
113
114		return $this->getRenderer($this->layout)->render($this->getLayoutData());
115	}
116
117	/**
118	 * Method to attach a JForm object to the field.
119	 *
120	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
121	 * @param   mixed             $value    The form field value to validate.
122	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
123	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
124	 *                                      full field name would end up being "bar[foo]".
125	 *
126	 * @return  boolean  True on success.
127	 *
128	 * @see     JFormField::setup()
129	 * @since   3.2
130	 */
131	public function setup(SimpleXMLElement $element, $value, $group = null)
132	{
133		$return = parent::setup($element, $value, $group);
134
135		if ($return)
136		{
137			$this->checkedOptions = (string) $this->element['checked'];
138		}
139
140		return $return;
141	}
142
143	/**
144	 * Method to get the data to be passed to the layout for rendering.
145	 *
146	 * @return  array
147	 *
148	 * @since   3.5
149	 */
150	protected function getLayoutData()
151	{
152		$data = parent::getLayoutData();
153
154		// True if the field has 'value' set. In other words, it has been stored, don't use the default values.
155		$hasValue = (isset($this->value) && !empty($this->value));
156
157		// If a value has been stored, use it. Otherwise, use the defaults.
158		$checkedOptions = $hasValue ? $this->value : $this->checkedOptions;
159
160		$extraData = array(
161			'checkedOptions' => is_array($checkedOptions) ? $checkedOptions : explode(',', (string) $checkedOptions),
162			'hasValue'       => $hasValue,
163			'options'        => $this->getOptions(),
164		);
165
166		return array_merge($data, $extraData);
167	}
168}
169