Issues (1686)

sources/ElkArte/AdminSettingsSearch.php (1 issue)

1
<?php
2
3
/**
4
 * Performs a search in an array of settings
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * This file contains code covered by:
11
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
12
 *
13
 * @version 2.0 dev
14
 *
15
 */
16
17
namespace ElkArte;
18
19
use ElkArte\Helper\Util;
20
use ElkArte\Languages\Txt;
21
22
/**
23
 * Perform a search in the admin settings (and maybe other settings as well)
24
 */
25
class AdminSettingsSearch
26
{
27
	/** @var array All the settings we have found */
28
	protected $_search_data;
29
30
	/** @var string Sections are supposed to be stored in a menu, and the menu is in $context['menu_name'] */
31
	protected $_menu_name;
32
33
	/** @var string[] An array of settings used in the search */
34
	protected $_settings = [];
35
36
	/**
37
	 * Constructor!
38
	 *
39
	 * @param string[] $language_files - Language file names
40
	 * @param string[] $include_files - File names to include (see _include_files for details on the structure)
41
	 * @param array $settings_search - Settings to search in (see _load_settings for details on the structure)
42
	 */
43
	public function __construct($language_files = [], $include_files = [], $settings_search = [])
44
	{
45
		if (!empty($language_files))
46
		{
47
			Txt::load(implode('+', $language_files));
48
		}
49
50
		if (!empty($include_files))
51
		{
52
			$this->_include_files($include_files);
53
		}
54
55 2
		if (!empty($settings_search))
56
		{
57 2
			$this->_settings = $this->_load_settings($settings_search);
58
		}
59 2
	}
60
61
	/**
62 2
	 * Includes a set of files.
63
	 *
64
	 * @param string[] $include_files - array of file names (without extension),
65
	 * it's possible to specify an array of arrays instead of an array of strings,
66
	 * in that case the index 0 is the directory of the file, while the 1 is the file name.
67 2
	 *
68
	 * If a directory is not specified it will default to the value of the constant ADMINDIR e.g.
69 2
	 * $include_files = array('file_name.controller', 'file_name2.controller', array('dir_name', 'file_name3.controller'))
70
	 */
71 2
	protected function _include_files($include_files)
72
	{
73
		foreach ($include_files as $file)
74
		{
75
			if (is_array($file))
76
			{
77
				$dir = $file[0];
78
				$file = $file[1];
79
			}
80
			else
81
			{
82
				$dir = ADMINDIR;
83
			}
84
85
			require_once($dir . '/' . $file . '.php');
86
		}
87
	}
88
89
	/**
90
	 * Loads all the settings
91
	 *
92
	 * @param array $settings_search - An array that defines where to look for settings. The structure is:
93
	 * array( method name, url, controller name )
94
	 *
95
	 * @return array
96
	 */
97
	private function _load_settings($settings_search)
98
	{
99
		$settings = [];
100
101
		foreach ($settings_search as $setting_area)
102
		{
103
			// Get a list of their variables.
104
			if (isset($setting_area[2]))
105
			{
106
				// an OOP controller: get the settings from the settings method.
107
				$controller = new $setting_area[2](new EventManager());
108
				$controller->setUser(User::$info);
109
				$controller->pre_dispatch();
110
				$config_vars = $controller->{$setting_area[0]}();
111
			}
112
			else
113
			{
114
				// a good ole' procedural controller: get the settings from the function.
115
				$config_vars = $setting_area[0](true);
116
			}
117
118
			foreach ($config_vars as $var)
119
			{
120 2
				if (empty($var[1]))
121
				{
122 2
					continue;
123
				}
124 2
125
				if (in_array($var[0], ['permissions', 'callback', 'message', 'warning', 'title', 'desc']))
126
				{
127 2
					continue;
128
				}
129
130 2
				$settings[] = [$this->_get_label($var), $setting_area[1], 'named_link' => $var[1]];
131 2
			}
132 2
		}
133 2
134
		return $settings;
135
	}
136
137
	/**
138
	 * Checks if any configuration settings have label text that should be included in the search
139
	 *
140
	 * @param array $var
141 2
	 *
142
	 * @return string
143 2
	 */
144
	private function _get_label($var)
145 2
	{
146
		global $txt;
147
148
		// Special case for file and db which go var, label, db, etc
149
		if (isset($var[2]) && in_array($var[2], ['file', 'db']))
150 2
		{
151
			$save = $var[1];
152
			$var[1] = $var[0];
153
		}
154
155
		// See if there are any labels that might fit?
156
		if (isset($var['text_label']))
157
		{
158
			return $var['text_label'];
159
		}
160
161 2
		if (isset($txt[$var[1]]))
162
		{
163 2
			return $txt[$var[1]];
164
		}
165
166 2
		if (isset($txt['setting_' . $var[1]]))
167
		{
168 2
			return $txt['setting_' . $var[1]];
169
		}
170
171
		if (isset($txt['groups_' . $var[1]]))
172 2
		{
173
			return $txt['groups_' . $var[1]];
174 2
		}
175
176
		if (!is_array($var) && isset($txt[$var]))
177 2
		{
178
			return $txt[$var];
179 2
		}
180
181
		return $save ?? $var[1];
182 2
	}
183
184 2
	/**
185
	 * Initialize the search populating the array to search in
186
	 *
187 2
	 * @param string $menu_name - The name of the menu to look into
188
	 * @param array $additional_settings - Possible additional settings (see _load_settings for the array structure)
189
	 */
190
	public function initSearch($menu_name, $additional_settings = [])
191
	{
192 2
		$this->_menu_name = $menu_name;
193
194
		// This is the huge array that defines everything ... it's items are formatted as follows:
195
		//	0 = Language index (Can be array of indexes) to search through for this setting.
196
		//	1 = URL for this indexes page.
197
		//	2 = Help index for help associated with this item (If different from 0)
198
		$this->_search_data = [
199
			// All the major sections of the forum.
200
			'sections' => $this->_load_search_sections(),
201
			'settings' => array_merge(
202 2
				$additional_settings,
203
				$this->_settings
204 2
			),
205
		];
206
	}
207
208
	/**
209
	 * Loads all the admin sections
210 2
	 */
211
	private function _load_search_sections()
212 2
	{
213 2
		global $context;
214 2
215 2
		$sections = [];
216
217
		// Go through the admin menu structure trying to find suitably named areas!
218 2
		foreach ($context[$this->_menu_name]['sections'] as $section)
219
		{
220
			foreach ($section['areas'] as $menu_key => $menu_item)
221
			{
222
				$sections[] = [$menu_item['label'], 'area=' . $menu_key, $menu_key];
223 2
				if (!empty($menu_item['subsections']))
224
				{
225 2
					foreach ($menu_item['subsections'] as $key => $sublabel)
226
					{
227 2
						if (isset($sublabel['label']))
228
						{
229
							$sections[] = [$sublabel['label'], 'area=' . $menu_key . ';sa=' . $key, $menu_key];
230 2
						}
231
					}
232 2
				}
233
			}
234 2
		}
235 2
236
		return $sections;
237 2
	}
238
239 2
	/**
240
	 * Actually perform the search of a term in the array
241 2
	 *
242
	 * @param string $search_term - The term to search
243
	 *
244
	 * @return string[] - an array of search results with 4 indexes:
245
	 *    - url
246
	 *    - name
247
	 *    - type
248 2
	 *    - help
249
	 */
250
	public function doSearch($search_term)
251
	{
252
		global $scripturl, $context;
253
254
		$search_results = [];
255
256
		foreach ($this->_search_data as $section => $data)
257
		{
258
			foreach ($data as $item)
259
			{
260
				$search_result = $this->_find_term($search_term, $item);
261
262 2
				if (!empty($search_result))
263
				{
264 2
					$search_result['type'] = $section;
265
					$search_result['url'] = $item[1] . ';' . $context['session_var'] . '=' . $context['session_id'];
266 2
267
					if (strpos($item[1], 'area') === 0)
268 2
					{
269
						$search_result['url'] = $scripturl . '?action=admin;' . $search_result['url'] . ($section === 'settings' && !empty($item['named_link']) ? '#' . $item['named_link'] : '');
270 2
					}
271
272 2
					$search_results[] = $search_result;
273
				}
274 2
			}
275
		}
276 2
277 2
		return $search_results;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $search_results returns an array which contains values of type string[] which are incompatible with the documented value type string.
Loading history...
278
	}
279 2
280
	/**
281 2
	 * Find a term inside an $item
282
	 *
283
	 * @param string $search_term - The term to search
284 2
	 * @param string|string[] $item - A string or array of strings that may be
285
	 * standalone strings, index for $txt, partial index for $txt['setting_' . $item]
286
	 *
287
	 * @return string[] - An empty array if $search_term is not found, otherwise
288
	 * part of the search_result array (consisting of 'name' and 'help')
289 2
	 * of the term the result was found
290
	 */
291
	protected function _find_term($search_term, $item)
292
	{
293
		global $helptxt;
294
295
		$found = false;
296
		$return = [];
297
298
		if (!is_array($item[0]))
299
		{
300
			$item[0] = [$item[0]];
301
		}
302
303 2
		foreach ($item[0] as $term)
304
		{
305 2
			if (stripos($term, $search_term) !== false)
306
			{
307 2
				$found = $term;
308 2
			}
309
		}
310 2
311
		// Format the name - and remove any descriptions the entry may have.
312 2
		if ($found !== false)
313
		{
314
			$name = preg_replace('~<(?:div|span)\sclass="smalltext">.+?</(?:div|span)>~s', '', $found);
315 2
316
			$return = [
317 2
				'name' => $name,
318
				'help' => Util::shorten_text(isset($item[2], $helptxt[$item[2]]) ? strip_tags($helptxt[$item[2]]) : (isset($helptxt[$found]) ? strip_tags($helptxt[$found]) : ''), 255),
319 2
			];
320
		}
321
322
		return $return;
323
	}
324
}
325