1 <?php
2
3 4 5
6 class rex_be_controller
7 {
8 9 10
11 private static $page;
12
13 14 15
16 private static $pageParts = [];
17
18 19 20
21 private static $pageObject;
22
23 24 25
26 private static $pages = [];
27
28 29 30
31 public static function setCurrentPage($page)
32 {
33 self::$page = trim($page, '/ ');
34 self::$pageParts = explode('/', self::$page);
35 self::$pageObject = null;
36 }
37
38 39 40
41 public static function getCurrentPage()
42 {
43 return self::$page;
44 }
45
46 47 48 49 50 51
52 public static function getCurrentPagePart($part = null, $default = null)
53 {
54 if ($part === null) {
55 return self::$pageParts;
56 }
57 --$part;
58 return isset(self::$pageParts[$part]) ? self::$pageParts[$part] : $default;
59 }
60
61 62 63
64 public static function getCurrentPageObject()
65 {
66 if (!self::$pageObject) {
67 self::$pageObject = self::getPageObject(self::getCurrentPage());
68 }
69 return self::$pageObject;
70 }
71
72 73 74 75 76
77 public static function getPageObject($page)
78 {
79 if (!is_array($page)) {
80 $page = explode('/', $page);
81 }
82 if (!isset($page[0]) || !isset(self::$pages[$page[0]])) {
83 return null;
84 }
85 $obj = self::$pages[$page[0]];
86 for ($i = 1, $count = count($page); $i < $count; ++$i) {
87 if ($new = $obj->getSubpage($page[$i])) {
88 $obj = $new;
89 } else {
90 return null;
91 }
92 }
93 return $obj;
94 }
95
96 97 98
99 public static function getPages()
100 {
101 return self::$pages;
102 }
103
104 105 106
107 public static function setPages(array $pages)
108 {
109 self::$pages = $pages;
110 }
111
112 public static function getPageTitle()
113 {
114 $parts = [];
115
116 $activePageObj = self::getCurrentPageObject();
117 if ($activePageObj->getTitle()) {
118 $parts[] = $activePageObj->getTitle();
119 }
120 if (rex::getServerName()) {
121 $parts[] = rex::getServerName();
122 }
123 $parts[] = 'REDAXO CMS';
124
125 return implode(' ยท ', $parts);
126 }
127
128 public static function getSetupPage()
129 {
130 $page = new rex_be_page('setup', rex_i18n::msg('setup'));
131 $page->setPath(rex_path::core('pages/setup.php'));
132 return $page;
133 }
134
135 public static function getLoginPage()
136 {
137 $page = new rex_be_page('login', 'Login');
138 $page->setPath(rex_path::core('pages/login.php'));
139 $page->setHasNavigation(false);
140 return $page;
141 }
142
143 public static function appendLoggedInPages()
144 {
145 self::$pages['profile'] = (new rex_be_page('profile', rex_i18n::msg('profile')))
146 ->setPath(rex_path::core('pages/profile.php'))
147 ->setPjax();
148
149 self::$pages['credits'] = (new rex_be_page('credits', rex_i18n::msg('credits')))
150 ->setPath(rex_path::core('pages/credits.php'));
151
152 self::$pages['packages'] = (new rex_be_page_main('system', 'packages', rex_i18n::msg('addons')))
153 ->setPath(rex_path::core('pages/packages.php'))
154 ->setRequiredPermissions('isAdmin')
155 ->setPrio(60)
156 ->setPjax()
157 ->setIcon('rex-icon rex-icon-package-addon');
158
159 $logsPage = (new rex_be_page('log', rex_i18n::msg('logfiles')))->setSubPath(rex_path::core('pages/system.log.php'));
160 $logsPage->addSubpage((new rex_be_page('redaxo', rex_i18n::msg('syslog_redaxo')))->setSubPath(rex_path::core('pages/system.log.redaxo.php')));
161 if (is_readable(ini_get('error_log'))) {
162 $logsPage->addSubpage((new rex_be_page('php', rex_i18n::msg('syslog_phperrors')))->setSubPath(rex_path::core('pages/system.log.external.php')));
163 }
164
165 self::$pages['system'] = (new rex_be_page_main('system', 'system', rex_i18n::msg('system')))
166 ->setPath(rex_path::core('pages/system.php'))
167 ->setRequiredPermissions('isAdmin')
168 ->setPrio(70)
169 ->setPjax()
170 ->setIcon('rex-icon rex-icon-system')
171 ->addSubpage((new rex_be_page('settings', rex_i18n::msg('main_preferences')))->setSubPath(rex_path::core('pages/system.settings.php')))
172 ->addSubpage((new rex_be_page('lang', rex_i18n::msg('languages')))->setSubPath(rex_path::core('pages/system.clangs.php')))
173 ->addSubpage($logsPage)
174 ->addSubpage((new rex_be_page('report', rex_i18n::msg('system_report')))
175 ->addSubpage((new rex_be_page('html', rex_i18n::msg('system_report')))->setSubPath(rex_path::core('pages/system.report.html.php')))
176 ->addSubpage((new rex_be_page('markdown', rex_i18n::msg('system_report_markdown')))->setSubPath(rex_path::core('pages/system.report.markdown.php')))
177 )
178 ->addSubpage((new rex_be_page('phpinfo', 'phpinfo'))
179 ->setHidden(true)
180 ->setHasLayout(false)
181 ->setPath(rex_path::core('pages/system.phpinfo.php'))
182 );
183 }
184
185 public static function appendPackagePages()
186 {
187 $insertPages = [];
188 $addons = rex::isSafeMode() ? rex_addon::getSetupAddons() : rex_addon::getAvailableAddons();
189 foreach ($addons as $addon) {
190 $mainPage = self::pageCreate($addon->getProperty('page'), $addon, true);
191
192 if (is_array($pages = $addon->getProperty('pages'))) {
193 foreach ($pages as $key => $page) {
194 if (strpos($key, '/') !== false) {
195 $insertPages[$key] = [$addon, $page];
196 } else {
197 self::pageCreate($page, $addon, false, $mainPage, $key, true);
198 }
199 }
200 }
201
202
203 $plugins = rex::isSafeMode() ? $addon->getSystemPlugins() : $addon->getAvailablePlugins();
204 foreach ($plugins as $plugin) {
205 self::pageCreate($plugin->getProperty('page'), $plugin, false, $mainPage);
206
207 if (is_array($pages = $plugin->getProperty('pages'))) {
208 foreach ($pages as $key => $page) {
209 if (strpos($key, '/') !== false) {
210 $insertPages[$key] = [$plugin, $page];
211 } else {
212 self::pageCreate($page, $plugin, false, $mainPage, $key, true);
213 }
214 }
215 }
216 }
217 }
218 foreach ($insertPages as $key => $packagePage) {
219 list($package, $page) = $packagePage;
220 $key = explode('/', $key);
221 if (!isset(self::$pages[$key[0]])) {
222 continue;
223 }
224 $parentPage = self::$pages[$key[0]];
225 for ($i = 1, $count = count($key) - 1; $i < $count && $parentPage; ++$i) {
226 $parentPage = $parentPage->getSubpage($key[$i]);
227 }
228 if ($parentPage) {
229 self::pageCreate($page, $package, false, $parentPage, $key[$i], strtr($parentPage->getFullKey(), '/', '.') . '.' . $key[$i] . '.');
230 }
231 }
232 }
233
234 235 236 237 238 239 240 241 242 243
244 private static function pageCreate($page, rex_package $package, $createMainPage, rex_be_page $parentPage = null, $pageKey = null, $prefix = false)
245 {
246 if (is_array($page) && isset($page['title'])) {
247 $pageArray = $page;
248 $pageKey = $pageKey ?: $package->getName();
249 if ($createMainPage || isset($pageArray['main']) && $pageArray['main']) {
250 $page = new rex_be_page_main('addons', $pageKey, $pageArray['title']);
251 } else {
252 $page = new rex_be_page($pageKey, $pageArray['title']);
253 }
254 self::pageAddProperties($page, $pageArray, $package);
255 }
256
257 if ($page instanceof rex_be_page) {
258 if (!is_string($prefix)) {
259 $prefix = $prefix ? $page->getKey() . '.' : '';
260 }
261 if ($page instanceof rex_be_page_main) {
262 if (!$page->hasPath()) {
263 $page->setPath($package->getPath('pages/' . ($prefix ?: 'index.') . 'php'));
264 }
265 self::$pages[$page->getKey()] = $page;
266 } else {
267 if (!$page->hasSubPath()) {
268 $page->setSubPath($package->getPath('pages/' . ($prefix ?: 'index.') . 'php'));
269 }
270 if ($parentPage) {
271 $parentPage->addSubpage($page);
272 }
273 }
274 self::pageSetSubPaths($page, $package, $prefix);
275 return $page;
276 }
277 return null;
278 }
279
280 281 282 283 284
285 private static function pageSetSubPaths(rex_be_page $page, rex_package $package, $prefix = '')
286 {
287 foreach ($page->getSubpages() as $subpage) {
288 if (!$subpage->hasSubPath()) {
289 $subpage->setSubPath($package->getPath('pages/' . $prefix . $subpage->getKey() . '.php'));
290 }
291 self::pageSetSubPaths($subpage, $package, $prefix . $subpage->getKey() . '.');
292 }
293 }
294
295 296 297 298 299
300 private static function pageAddProperties(rex_be_page $page, array $properties, rex_package $package)
301 {
302 foreach ($properties as $key => $value) {
303 switch (strtolower($key)) {
304 case 'subpages':
305 if (is_array($value)) {
306 foreach ($value as $pageKey => $subProperties) {
307 if (isset($subProperties['title'])) {
308 $subpage = new rex_be_page($pageKey, $subProperties['title']);
309 $page->addSubpage($subpage);
310 self::pageAddProperties($subpage, $subProperties, $package);
311 }
312 }
313 }
314 break;
315
316 case 'itemattr':
317 case 'linkattr':
318 $setter = [$page, 'set' . ucfirst($key)];
319 foreach ($value as $k => $v) {
320 call_user_func($setter, $k, $v);
321 }
322 break;
323
324 case 'perm':
325 $page->setRequiredPermissions($value);
326 break;
327
328 case 'path':
329 case 'subpath':
330 if (file_exists($path = $package->getPath($value))) {
331 $value = $path;
332 }
333
334 default:
335 $setter = [$page, 'add' . ucfirst($key)];
336 if (is_callable($setter)) {
337 foreach ((array) $value as $v) {
338 call_user_func($setter, $v);
339 }
340 break;
341 }
342 $setter = [$page, 'set' . ucfirst($key)];
343 if (is_callable($setter)) {
344 call_user_func($setter, $value);
345 }
346 }
347 }
348 }
349
350 public static function checkPagePermissions(rex_user $user)
351 {
352 $check = function (rex_be_page $page) use (&$check, $user) {
353 if (!$page->checkPermission($user)) {
354 return false;
355 }
356
357 $subpages = $page->getSubpages();
358 foreach ($subpages as $key => $subpage) {
359 if (!$check($subpage)) {
360 unset($subpages[$key]);
361 }
362 }
363 $page->setSubpages($subpages);
364
365 return true;
366 };
367
368 foreach (self::$pages as $key => $page) {
369 if (!$check($page)) {
370 unset(self::$pages[$key]);
371 }
372 }
373 self::$pageObject = null;
374
375 $page = self::getCurrentPageObject();
376
377 if (!$page) {
378
379 $page = self::getPageObject($user->getStartPage());
380 if (!$page) {
381
382 $page = self::getPageObject(rex::getProperty('start_page'));
383 if (!$page) {
384
385 $page = self::getPageObject('profile');
386 }
387 }
388 rex_response::setStatus(rex_response::HTTP_NOT_FOUND);
389 rex_response::sendRedirect($page->getHref());
390 }
391 if ($page !== $leaf = $page->getFirstSubpagesLeaf()) {
392 rex_response::setStatus(rex_response::HTTP_MOVED_PERMANENTLY);
393 $url = $leaf->hasHref() ? $leaf->getHref() : rex_context::fromGet()->getUrl(['page' => $leaf->getFullKey()], false);
394 rex_response::sendRedirect($url);
395 }
396 }
397
398 399 400
401 public static function includeCurrentPage()
402 {
403 $currentPage = self::getCurrentPageObject();
404
405 if (rex_request::isPJAXRequest() && !rex_request::isPJAXContainer('#rex-js-page-container')) {
406
407
408 $currentPage->setHasLayout(false);
409 }
410
411 require rex_path::core('layout/top.php');
412
413 self::includePath($currentPage->getPath());
414
415 require rex_path::core('layout/bottom.php');
416 }
417
418 419 420 421 422 423 424
425 public static function includeCurrentPageSubPath(array $context = [])
426 {
427 $path = self::getCurrentPageObject()->getSubPath();
428
429 if ('.md' !== strtolower(substr($path, -3))) {
430 return self::includePath($path, $context);
431 }
432
433 $languagePath = substr($path, 0, -3).'.'.rex_i18n::getLanguage().'.md';
434 if (is_readable($languagePath)) {
435 $path = $languagePath;
436 }
437
438 list($toc, $content) = rex_markdown::factory()->parseWithToc(rex_file::get($path));
439 $fragment = new rex_fragment();
440 $fragment->setVar('content', $content, false);
441 $fragment->setVar('toc', $toc, false);
442 $content = $fragment->parse('core/page/docs.php');
443
444 $fragment = new rex_fragment();
445 $fragment->setVar('title', self::getCurrentPageObject()->getTitle(), false);
446 $fragment->setVar('body', $content, false);
447 echo $fragment->parse('core/page/section.php');
448 }
449
450 451 452 453 454 455 456 457
458 private static function includePath($path, array $context = [])
459 {
460 $pattern = '@' . preg_quote(rex_path::src('addons/'), '@') . '([^/\\\]+)(?:[/\\\]plugins[/\\\]([^/\\\]+))?@';
461
462 if (!preg_match($pattern, $path, $matches)) {
463 $__context = $context;
464 $__path = $path;
465 unset($context, $path, $pattern, $matches);
466 extract($__context, EXTR_SKIP);
467 return include $__path;
468 }
469
470 $package = rex_addon::get($matches[1]);
471 if (isset($matches[2])) {
472 $package = $package->getPlugin($matches[2]);
473 }
474 return $package->includeFile(str_replace($package->getPath(), '', $path), $context);
475 }
476 }
477