36885b86f8e03a67ab4bd0d92de59a4c8991bdd5
[Packages/TYPO3.CMS.git] / typo3 / sysext / lowlevel / Classes / Utility / ArrayBrowser.php
1 <?php
2 namespace TYPO3\CMS\Lowlevel\Utility;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\MathUtility;
21
22 /**
23 * Class for displaying an array as a tree
24 * See the extension 'lowlevel' /config (Backend module 'Tools > Configuration')
25 *
26 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
27 */
28 class ArrayBrowser {
29
30 /**
31 * @var bool
32 */
33 public $expAll = FALSE;
34
35 /**
36 * If set, will expand all (depthKeys is obsolete then) (and no links are applied)
37 *
38 * @var bool
39 */
40 public $dontLinkVar = FALSE;
41
42 /**
43 * If set, the variable keys are not linked.
44 *
45 * @var array
46 */
47 public $depthKeys = array();
48
49 /**
50 * Array defining which keys to expand. Typically set from outside from some session
51 * variable - otherwise the array will collapse.
52 *
53 * @var array
54 */
55 public $searchKeys = array();
56
57 /**
58 * After calling the getSearchKeys function this array is populated with the
59 * key-positions in the array which contains values matching the search.
60 *
61 * @var int
62 */
63 public $fixedLgd = 1;
64
65 /**
66 * If set, the values are truncated with "..." appended if longer than a certain
67 * length.
68 *
69 * @var int
70 */
71 public $regexMode = 0;
72
73 /**
74 * If set, search for string with regex, otherwise stristr()
75 *
76 * @var bool
77 */
78 public $searchKeysToo = FALSE;
79
80 /**
81 * If set, array keys are subject to the search too.
82 *
83 * @var string
84 */
85 public $varName = '';
86
87 /**
88 * Set var name here if you want links to the variable name.
89 *
90 * Make browseable tree
91 * Before calling this function you may want to set some of the internal vars like
92 * depthKeys, regexMode and fixedLgd.
93 *
94 * @param array $array The array to display
95 * @param string $positionKey Key-position id. Build up during recursive calls - [key1].[key2].[key3] - an so on.
96 * @param string $depthData is deprecated since TYPO3 CMS 7, and will be removed with CMS 8
97 * @return string HTML for the tree
98 */
99 public function tree($array, $positionKey, $depthData = NULL) {
100 if ($depthData) {
101 GeneralUtility::deprecationLog('ArrayBrowser::tree parameter $depthData is deprecated since TYPO3 CMS 7 and is not used anymore. Please remove the parameter.');
102 }
103 $output = '<ul class="list-tree text-monospace">';
104 if ($positionKey) {
105 $positionKey = $positionKey . '.';
106 }
107 foreach ($array as $key => $value) {
108 $depth = $positionKey . $key;
109 if (is_object($value) && !$value instanceof \Traversable) {
110 $value = (array)$value;
111 }
112 $isArray = is_array($value) || $value instanceof \Traversable;
113 $isResult = (bool)$this->searchKeys[$depth];
114 $isExpanded = $isArray && ($this->depthKeys[$depth] || $this->expAll);
115 $output .= '<li' . ($isResult ? ' class="active"' : '') . '>';
116 if ($isArray && !$this->expAll) {
117 $goto = 'a' . substr(md5($depth), 0, 6);
118 $output .= '<a class="list-tree-control' . ($isExpanded ? ' list-tree-control-open' : ' list-tree-control-closed') . '" id="' . $goto . '" href="' . htmlspecialchars((BackendUtility::getModuleUrl(GeneralUtility::_GP('M')) . '&node[' . $depth . ']=' . ($isExpanded ? 0 : 1) . '#' . $goto)) . '"><i class="fa"></i></a> ';
119 }
120 $output .= '<span class="list-tree-group">';
121 $output .= $this->wrapArrayKey($key, $depth, !$isArray ? $value : '');
122 if (!$isArray) {
123 $output .= ' = <span class="list-tree-value">' . $this->wrapValue($value) . '</span>';
124 }
125 $output .= '</span>';
126 if ($isExpanded) {
127 $output .= $this->tree(
128 $value,
129 $depth
130 );
131 }
132 $output .= '</li>';
133 }
134 $output .= '</ul>';
135 return $output;
136 }
137
138 /**
139 * Wrapping the value in bold tags etc.
140 *
141 * @param string $theValue The title string
142 * @return string Title string, htmlspecialchars()'ed
143 */
144 public function wrapValue($theValue) {
145 $wrappedValue = '';
146 if ((string)$theValue !== '') {
147 $wrappedValue = htmlspecialchars($theValue);
148 }
149 return $wrappedValue;
150 }
151
152 /**
153 * Wrapping the value in bold tags etc.
154 *
155 * @param string $label The title string
156 * @param string $depth Depth path
157 * @param string $theValue The value for the array entry.
158 * @return string Title string, htmlspecialchars()'ed
159 */
160 public function wrapArrayKey($label, $depth, $theValue) {
161 // Protect label:
162 $label = htmlspecialchars($label);
163
164 // If varname is set:
165 if ($this->varName && !$this->dontLinkVar) {
166 $variableName = $this->varName
167 . '[\'' . str_replace('.', '\'][\'', $depth) . '\'] = '
168 . (!MathUtility::canBeInterpretedAsInteger($theValue) ? '\''
169 . addslashes($theValue) . '\'' : $theValue) . '; ';
170 $label = '<a class="list-tree-label" href="'
171 . htmlspecialchars((BackendUtility::getModuleUrl(GeneralUtility::_GP('M'))
172 . '&varname=' . urlencode($variableName)))
173 . '#varname">' . $label . '</a>';
174 }
175
176 return $label;
177 }
178
179 /**
180 * Creates an array with "depthKeys" which will expand the array to show the search results
181 *
182 * @param array $keyArr The array to search for the value
183 * @param string $depth_in Depth string - blank for first call (will build up during recursive calling creating
184 * an id of the position: [key1].[key2].[key3]
185 * @param string $searchString The string to search for
186 * @param array $keyArray Key array, for first call pass empty array
187 * @return array
188 */
189 public function getSearchKeys($keyArr, $depth_in, $searchString, $keyArray) {
190 if ($depth_in) {
191 $depth_in = $depth_in . '.';
192 }
193 foreach ($keyArr as $key => $value) {
194 $depth = $depth_in . $key;
195 $deeper = is_array($keyArr[$key]);
196 if ($this->regexMode) {
197 if (
198 preg_match('/' . $searchString . '/', $keyArr[$key])
199 || $this->searchKeysToo && preg_match('/' . $searchString . '/', $key)
200 ) {
201 $this->searchKeys[$depth] = 1;
202 }
203 } else {
204 if (
205 !$deeper && stristr($keyArr[$key], $searchString)
206 || $this->searchKeysToo && stristr($key, $searchString)
207 ) {
208 $this->searchKeys[$depth] = 1;
209 }
210 }
211 if ($deeper) {
212 $cS = count($this->searchKeys);
213 $keyArray = $this->getSearchKeys($keyArr[$key], $depth, $searchString, $keyArray);
214 if ($cS != count($this->searchKeys)) {
215 $keyArray[$depth] = 1;
216 }
217 }
218 }
219 return $keyArray;
220 }
221
222 /**
223 * Function modifying the depthKey array
224 *
225 * @param array $arr Array with instructions to open/close nodes.
226 * @param array $settings Input depth_key array
227 * @return array Output depth_key array with entries added/removed based on $arr
228 */
229 public function depthKeys($arr, $settings) {
230 $tsbrArray = array();
231 foreach ($arr as $theK => $theV) {
232 $theKeyParts = explode('.', $theK);
233 $depth = '';
234 $c = count($theKeyParts);
235 $a = 0;
236 foreach ($theKeyParts as $p) {
237 $a++;
238 $depth .= ($depth ? '.' : '') . $p;
239 $tsbrArray[$depth] = $c == $a ? $theV : 1;
240 }
241 }
242 // Modify settings
243 foreach ($tsbrArray as $theK => $theV) {
244 if ($theV) {
245 $settings[$theK] = 1;
246 } else {
247 unset($settings[$theK]);
248 }
249 }
250 return $settings;
251 }
252
253 }