PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.21
VikAppointments Services Booking Calendar v1.2.21
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / libraries / mvc / admin / views / overrides / view.html.php
vikappointments / libraries / mvc / admin / views / overrides Last commit date
tmpl 5 days ago view.html.php 5 days ago
view.html.php
309 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2024 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * VikAppointments Overrides view.
16 * @wponly
17 *
18 * @since 1.2.13
19 */
20 class VikAppointmentsViewOverrides extends JView
21 {
22 /**
23 * @override
24 * View display method.
25 *
26 * @return void
27 */
28 public function display($tpl = null)
29 {
30 $input = JFactory::getApplication()->input;
31 $user = JFactory::getUser();
32
33 if (!$user->authorise('core.admin', 'com_vikappointments'))
34 {
35 wp_die(
36 '<h1>' . JText::translate('FATAL_ERROR') . '</h1>' .
37 '<p>' . JText::translate('RESOURCE_AUTH_ERROR') . '</p>',
38 403
39 );
40 }
41
42 // load filters from request
43 $filters = [];
44 $filters['client'] = $input->get('client', 'site', 'string');
45 $filters['status'] = $input->get('status', '', 'string');
46 $filters['file'] = $input->get('selectedfile', '', 'base64');
47 $filters['override'] = $input->get('overridefile', '', 'base64');
48
49 $filters['hasoverride'] = false;
50 $filters['published'] = false;
51
52 // get view model
53 $model = $this->getModel();
54
55 // scan overrides tree
56 $this->tree = $model->getTree($filters['client']);
57
58 // check whether a file was specified
59 if ($filters['file'])
60 {
61 // decode file path
62 $filters['path'] = base64_decode($filters['file']);
63 $filters['override'] = base64_decode($filters['override']);
64 }
65 else if ($filters['override'])
66 {
67 // override provided, attempt to fetch the path of the original file
68 $filters['override'] = base64_decode($filters['override']);
69
70 // search node with matching override file
71 $node = $model->isSupported($this->tree, $filters['override']);
72
73 if ($node)
74 {
75 // node found
76 $filters['file'] = base64_encode($node['path']);
77 $filters['path'] = $node['path'];
78 }
79 else
80 {
81 // node not found
82 $filters['path'] = false;
83 $filters['override'] = '';
84 }
85 }
86 else
87 {
88 // no selected file
89 $filters['path'] = false;
90 }
91
92 // check if we should filter the tree according to the specified status
93 if ($filters['status'] !== '')
94 {
95 // apply filters
96 foreach ($this->tree as $i => &$node)
97 {
98 // apply filters to the first level nodes
99 if (!$this->filterOverrides($this->tree[$i], (int) $filters['status']))
100 {
101 // detach node as there are no matching overrides
102 unset($this->tree[$i]);
103 }
104 }
105 }
106
107 // in case of selected file, make sure it supports overrides
108 if ($filters['path'])
109 {
110 // invoke model check
111 $supported = $model->isSupported($this->tree, $filters['path']);
112
113 if ($supported)
114 {
115 // read default file contents
116 $filters['defaultcode'] = file_get_contents($filters['path']);
117
118 // override supported, check if already exists
119 if (JFile::exists($filters['override']))
120 {
121 // existing override, read contents
122 $filters['code'] = file_get_contents($filters['override']);
123
124 $filters['hasoverride'] = true;
125
126 $filters['published'] = true;
127 }
128 else
129 {
130 // override is missing, look for an unpublished override
131 $_path = JPath::clean(dirname($filters['override']) . '/__' . basename($filters['override']));
132
133 if (JFile::exists($_path))
134 {
135 // existing unpublished override, read contents
136 $filters['code'] = file_get_contents($_path);
137
138 $filters['hasoverride'] = true;
139 }
140 else
141 {
142 // no override, use default code
143 $filters['code'] = $filters['defaultcode'];
144 }
145 }
146
147 /**
148 * Adjust the comments describing the layout location
149 * to the wordpress structure.
150 */
151 $filters['code'] = preg_replace_callback(
152 "/\*\s*(\/administrator)?\/?components\/com_vikappointments(.*?)\R/i",
153 function($match)
154 {
155 return '* /wp-content/plugins/vikappointments/'
156 . ($match[1] ? 'admin' : 'site')
157 . $match[2] . "\n";
158 },
159 $filters['code']
160 );
161
162 // detect differences among the override and the original file
163 $filters['differences'] = $model->calcDiff($filters['code'], $filters['defaultcode']);
164 }
165 else
166 {
167 // the selected file doesn't support overrides, unset selection
168 $filters['file'] = '';
169 $filters['override'] = '';
170 $filters['path'] = false;
171 }
172 }
173
174 // register filters
175 $this->filters = $filters;
176
177 // set up toolbar
178 $this->addToolbar();
179
180 // display parent
181 parent::display($tpl);
182 }
183
184 /**
185 * Helper method to setup the toolbar.
186 *
187 * @return void
188 */
189 public function addToolbar()
190 {
191 JToolbarHelper::title(__('VikAppointments - Page Overrides', 'vikappointments'));
192
193 // back to the configuration
194 JToolbarHelper::back('JTOOLBAR_BACK', 'index.php?option=com_vikappointments&view=editconfigapp');
195
196 // check if we have a selected file
197 if ($this->filters['path'])
198 {
199 // add save button
200 JToolbarHelper::apply('override.save');
201 }
202 }
203
204 /**
205 * Helper function used to build a navigator node.
206 *
207 * @param array $node The tree node.
208 *
209 * @return string The HTML to display.
210 */
211 protected function buildNode($node)
212 {
213 // in case the selected path contains the current node, mark the node as selected
214 if ($this->filters['path'] && strpos($this->filters['path'], $node['path'] . '/') === 0)
215 {
216 $node['selected'] = true;
217 }
218 else
219 {
220 $node['selected'] = false;
221 }
222
223 // set up current node
224 $this->currentNode = $node;
225
226 if ($node['folder'])
227 {
228 // build folder link
229 $html = $this->loadTemplate('folder');
230 }
231 else
232 {
233 // build file link
234 $html = $this->loadTemplate('file');
235 }
236
237 // check whether the node is a leaf
238 if (!empty($node['files']))
239 {
240 // fetch node children visibility
241 $style = $node['selected'] ? '' : ' style="display:none;"';
242
243 // create children list
244 $html .= '<ul' . $style . '>';
245
246 // iterate children
247 foreach ($node['files'] as $file)
248 {
249 // create child node
250 $html .= '<li>';
251 // build child HTML
252 $html .= $this->buildNode($file);
253 // close child node
254 $html .= '</li>';
255 }
256
257 // close children list
258 $html .= '</ul>';
259 }
260
261 return $html;
262 }
263
264 /**
265 * Filter the available pages/widgets/layouts according to the specified status.
266 *
267 * @param array &$node The node holding the available files.
268 * @param int $status The filter status (1: active only, 0: inactive only).
269 *
270 * @return void
271 */
272 protected function filterOverrides(array &$node, int $status)
273 {
274 // scan all the files of the node
275 foreach ($node['files'] as $k => &$file)
276 {
277 // check whether we have a sub-level node
278 if (isset($file['files']))
279 {
280 // recursively filter the overrides under this sub-level
281 if (!$this->filterOverrides($file, $status))
282 {
283 // retach the sub-level in case it has no overrides
284 unset($node['files'][$k]);
285 }
286 }
287 // or if we have a leaf (file override)
288 else
289 {
290 // make sure the file has an override and it matches the provided status
291 if (!$file['has'] || $file['published'] != $status)
292 {
293 // not compliant, detach file override
294 unset($node['files'][$k]);
295 }
296 }
297 }
298
299 if (count($node['files']) === 0)
300 {
301 // return false in case the node should be detached from the tree
302 return false;
303 }
304
305 // the node contains at least a matching override
306 return true;
307 }
308 }
309