1<?php
2/**
3 * Joomla! Content Management System
4 *
5 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
6 * @license    GNU General Public License version 2 or later; see LICENSE.txt
7 */
8
9namespace Joomla\CMS\Form\Field;
10
11defined('JPATH_PLATFORM') or die;
12
13use Joomla\CMS\Factory;
14use Joomla\CMS\Form\FormHelper;
15
16FormHelper::loadFieldClass('groupedlist');
17
18/**
19 * Chrome Styles field.
20 *
21 * @since  3.0
22 */
23class ChromestyleField extends \JFormFieldGroupedList
24{
25	/**
26	 * The form field type.
27	 *
28	 * @var    string
29	 * @since  3.0
30	 */
31	public $type = 'ChromeStyle';
32
33	/**
34	 * The client ID.
35	 *
36	 * @var    integer
37	 * @since  3.2
38	 */
39	protected $clientId;
40
41	/**
42	 * Method to get certain otherwise inaccessible properties from the form field object.
43	 *
44	 * @param   string  $name  The property name for which to get the value.
45	 *
46	 * @return  mixed  The property value or null.
47	 *
48	 * @since   3.2
49	 */
50	public function __get($name)
51	{
52		switch ($name)
53		{
54			case 'clientId':
55				return $this->clientId;
56		}
57
58		return parent::__get($name);
59	}
60
61	/**
62	 * Method to set certain otherwise inaccessible properties of the form field object.
63	 *
64	 * @param   string  $name   The property name for which to get the value.
65	 * @param   mixed   $value  The value of the property.
66	 *
67	 * @return  void
68	 *
69	 * @since   3.2
70	 */
71	public function __set($name, $value)
72	{
73		switch ($name)
74		{
75			case 'clientId':
76				$this->clientId = (string) $value;
77				break;
78
79			default:
80				parent::__set($name, $value);
81		}
82	}
83
84	/**
85	 * Method to attach a JForm object to the field.
86	 *
87	 * @param   \SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
88	 * @param   mixed              $value    The form field value to validate.
89	 * @param   string             $group    The field name group control value. This acts as an array container for the field.
90	 *                                       For example if the field has name="foo" and the group value is set to "bar" then the
91	 *                                       full field name would end up being "bar[foo]".
92	 *
93	 * @return  boolean  True on success.
94	 *
95	 * @see     JFormField::setup()
96	 * @since   3.2
97	 */
98	public function setup(\SimpleXMLElement $element, $value, $group = null)
99	{
100		$result = parent::setup($element, $value, $group);
101
102		if ($result === true)
103		{
104			// Get the client id.
105			$clientId = $this->element['client_id'];
106
107			if (!isset($clientId))
108			{
109				$clientName = $this->element['client'];
110
111				if (isset($clientName))
112				{
113					$client = \JApplicationHelper::getClientInfo($clientName, true);
114					$clientId = $client->id;
115				}
116			}
117
118			if (!isset($clientId) && $this->form instanceof \JForm)
119			{
120				$clientId = $this->form->getValue('client_id');
121			}
122
123			$this->clientId = (int) $clientId;
124		}
125
126		return $result;
127	}
128
129
130	/**
131	 * Method to get the list of template chrome style options
132	 * grouped by template.
133	 *
134	 * @return  array  The field option objects as a nested array in groups.
135	 *
136	 * @since   3.0
137	 */
138	protected function getGroups()
139	{
140		$groups = array();
141
142		// Add Module Style Field
143		$tmp = '---' . \JText::_('JLIB_FORM_VALUE_FROM_TEMPLATE') . '---';
144		$groups[$tmp][] = \JHtml::_('select.option', '0', \JText::_('JLIB_FORM_VALUE_INHERITED'));
145
146		$templateStyles = $this->getTemplateModuleStyles();
147
148		// Create one new option object for each available style, grouped by templates
149		foreach ($templateStyles as $template => $styles)
150		{
151			$template = ucfirst($template);
152			$groups[$template] = array();
153
154			foreach ($styles as $style)
155			{
156				$tmp = \JHtml::_('select.option', $template . '-' . $style, $style);
157				$groups[$template][] = $tmp;
158			}
159		}
160
161		reset($groups);
162
163		return $groups;
164	}
165
166	/**
167	 * Method to get the templates module styles.
168	 *
169	 * @return  array  The array of styles, grouped by templates.
170	 *
171	 * @since   3.0
172	 */
173	protected function getTemplateModuleStyles()
174	{
175		$moduleStyles = array();
176
177		$templates = array($this->getSystemTemplate());
178		$templates = array_merge($templates, $this->getTemplates());
179		$path      = JPATH_ADMINISTRATOR;
180
181		if ($this->clientId === 0)
182		{
183			$path = JPATH_SITE;
184		}
185
186		foreach ($templates as $template)
187		{
188			$modulesFilePath = $path . '/templates/' . $template->element . '/html/modules.php';
189
190			// Is there modules.php for that template?
191			if (file_exists($modulesFilePath))
192			{
193				$modulesFileData = file_get_contents($modulesFilePath);
194
195				preg_match_all('/function[\s\t]*modChrome\_([a-z0-9\-\_]*)[\s\t]*\(/i', $modulesFileData, $styles);
196
197				if (!array_key_exists($template->element, $moduleStyles))
198				{
199					$moduleStyles[$template->element] = array();
200				}
201
202				$moduleStyles[$template->element] = $styles[1];
203			}
204		}
205
206		return $moduleStyles;
207	}
208
209	/**
210	 * Method to get the system template as an object.
211	 *
212	 * @return  \stdClass  The object of system template.
213	 *
214	 * @since   3.0
215	 */
216	protected function getSystemTemplate()
217	{
218		$template = new \stdClass;
219		$template->element = 'system';
220		$template->name    = 'system';
221
222		return $template;
223	}
224
225	/**
226	 * Return a list of templates
227	 *
228	 * @return  array  List of templates
229	 *
230	 * @since   3.2.1
231	 */
232	protected function getTemplates()
233	{
234		$db = Factory::getDbo();
235
236		// Get the database object and a new query object.
237		$query = $db->getQuery(true);
238
239		// Build the query.
240		$query->select('element, name')
241			->from('#__extensions')
242			->where('client_id = ' . $this->clientId)
243			->where('type = ' . $db->quote('template'))
244			->where('enabled = 1');
245
246		// Set the query and load the templates.
247		$db->setQuery($query);
248
249		return $db->loadObjectList('element');
250	}
251}
252