Automad
 All Classes Functions Variables Pages
gui.php
1 <?php
2 /*
3  * ....
4  * .: '':.
5  * :::: ':..
6  * ::. ''..
7  * .:'.. ..':.:::' . :. '':.
8  * :. '' '' '. ::::.. ..:
9  * ::::. ..':.. .'''::::: .
10  * :::::::.. '..:::: :. :::: :
11  * ::'':::::::. ':::.'':.:::: :
12  * :.. ''::::::....': '':: :
13  * :::::. '::::: : .. '' .
14  * .''::::::::... ':::.'' ..'' :.''''.
15  * :..:::''::::: :::::...:'' :..:
16  * ::::::. ':::: :::::::: ..:: .
17  * ::::::::.:::: :::::::: :'':.:: .''
18  * ::: '::::::::.' ''::::: :.' '': :
19  * ::: :::::::::..' :::: ::...' .
20  * ::: .:::::::::: :::: :::: .:'
21  * '::' ''::::::: :::: : :: :
22  * ':::: :::: :'' .:
23  * :::: :::: ..''
24  * :::: ..:::: .:''
25  * '''' '''''
26  *
27  *
28  * AUTOMAD
29  *
30  * Copyright (c) 2014 by Marc Anton Dahmen
31  * http://marcdahmen.de
32  *
33  * Licensed under the MIT license.
34  * http://automad.org/license
35  */
36 
37 
38 namespace Automad\GUI;
39 
40 
41 defined('AUTOMAD') or die('Direct access not permitted!');
42 
43 
52 class GUI {
53 
54 
59  private $collection;
60 
61 
66  private $guiTitle = 'Automad';
67 
68 
73  public $output;
74 
75 
80  private $siteData;
81 
82 
87  private $tb = array();
88 
89 
108  public function __construct() {
109 
110  // Get Site data.
111  $this->siteData = \Automad\Core\Parse::siteData();
112 
113  // Get all GUI text blocks.
114  $this->tb = \Automad\Core\Parse::markdownFile(AM_BASE_DIR . '/automad/gui/text_blocks.txt');
115 
116  // Start Session.
117  session_start();
118 
119  // Check if an user is logged in.
120  if ($this->user()) {
121 
122  // If user is logged in, continue with getting the Automad object and the collection.
123  $Automad = new \Automad\Core\Automad(false);
124  $this->collection = $Automad->getCollection();
125 
126  // Check if context/ajax matches an existing .php file.
127  // If there is no (or no matching context), load the start page.
128  if (in_array(AM_BASE_DIR . AM_DIR_GUI_INC . '/context/' . \Automad\Core\Parse::queryKey('context') . '.php', glob(AM_BASE_DIR . AM_DIR_GUI_INC . '/context/*.php'))) {
129  $inc = 'context/' . \Automad\Core\Parse::queryKey('context');
130  } else if (in_array(AM_BASE_DIR . AM_DIR_GUI_INC . '/ajax/' . \Automad\Core\Parse::queryKey('ajax') . '.php', glob(AM_BASE_DIR . AM_DIR_GUI_INC . '/ajax/*.php'))) {
131  $inc = 'ajax/' . \Automad\Core\Parse::queryKey('ajax');
132  } else {
133  $inc = 'start';
134  }
135 
136  } else {
137 
138  // If no user is logged in, check if accounts.txt exists. If yes, set $inc to the login page, else to the installer.
139  if (file_exists(AM_FILE_ACCOUNTS)) {
140  $inc = 'login';
141  } else {
142  $inc = 'install';
143  }
144 
145  }
146 
147  // Buffer the HTML to merge the output with the debug log in init.php.
148  ob_start();
149 
150  // Load page according to the current context.
151  require AM_BASE_DIR . AM_DIR_GUI_INC . '/' . $inc . '.php';
152 
153  $this->output = ob_get_contents();
154  ob_end_clean();
155 
156  }
157 
158 
169  private function accountsGeneratePHP($accounts) {
170 
171  return "<?php defined('AUTOMAD') or die('Direct access not permitted!');\n" .
172  'return unserialize(\'' . serialize($accounts) . '\');' .
173  "\n?>";
174 
175  }
176 
177 
184  private function accountsGetArray() {
185 
186  return (include AM_FILE_ACCOUNTS);
187 
188  }
189 
190 
197  private function accountsSaveArray($accounts) {
198 
199  return @file_put_contents(AM_FILE_ACCOUNTS, $this->accountsGeneratePHP($accounts));
200 
201  }
202 
203 
210  private function element($element) {
211 
212  require AM_BASE_DIR . AM_DIR_GUI_INC . '/elements/' . $element . '.php';
213 
214  }
215 
216 
223  private function extractPrefixFromPath($path) {
224 
225  return substr(basename($path), 0, strpos(basename($path), '.'));
226 
227  }
228 
229 
239  private function getPageVarsInTemplate($theme, $template) {
240 
241  // A new full (!) Automad object has to be created, since the template's methods need all page data to succeed.
242  $Automad = new \Automad\Core\Automad();
243 
244  // Get template form the Site's theme, if $theme is false.
245  if (!$theme) {
246  $theme = $this->siteData[AM_KEY_THEME];
247  }
248 
249  $file = AM_BASE_DIR . AM_DIR_THEMES . '/' . $theme . '/' . $template . '.php';
250 
251  // Get template file content including all nested elements.
252  $content = \Automad\Core\Parse::templateBuffer($file, $Automad);
253  $content = \Automad\Core\Parse::templateNestedIncludes($content, dirname($file), $Automad);
254 
255  // Find all variables within the template existing before parsing any method.
256  preg_match_all(AM_REGEX_PAGE_VAR, $content, $matches);
257 
258  $vars = $matches[1];
259 
260  // Parse all the template's methods to get also the variables generated by these methods.
261  // In case the page gets redirected, the parsing gets skipped to avoid errors due to the fact, that $Page->url won't be a key
262  // within the $collection array. That issue only occures when the GUI parses these pages, since the would normally be redirected before parsing.
263  if (!isset($Automad->getCurrentPage()->data[AM_KEY_URL])) {
264  $content = \Automad\Core\Parse::templateMethods($content, $Automad);
265  }
266 
267  // Now find all variables generated by the template's methods by parsing again the content for the second time.
268  preg_match_all(AM_REGEX_PAGE_VAR, $content, $matches);
269 
270  $vars = array_merge($vars, $matches[1]);
271 
272  // Clean up before returning to remove all doubled items due to parsing twice (before parsing methods and after).
273  // All variables are stored in $vars in order of appearance.
274  return array_unique($vars);
275 
276  }
277 
278 
290  private function getSiteVarsInThemes() {
291 
292  // Collect all .php files below "/themes"
293  $dir = AM_BASE_DIR . AM_DIR_THEMES;
294  $arrayDirs = array();
295  $arrayFiles = array();
296 
297  while ($dirs = glob($dir . '/*', GLOB_ONLYDIR)) {
298  $dir .= '/*';
299  $arrayDirs = array_merge($arrayDirs, $dirs);
300  }
301 
302  foreach ($arrayDirs as $d) {
303  if ($f = glob($d . '/*.php')) {
304  $arrayFiles = array_merge($arrayFiles, $f);
305  }
306  }
307 
308  // Scan content of all the files for site variables.
309  $content = '';
310 
311  foreach ($arrayFiles as $file) {
312  $content .= file_get_contents($file);
313  }
314 
315  preg_match_all(AM_REGEX_SITE_VAR, $content, $matches);
316  sort($matches[1]);
317 
318  return array_unique($matches[1]);
319 
320  }
321 
322 
335  private function movePage($oldPath, $newParentPath, $prefix, $title) {
336 
337  // Normalize parent path.
338  $newParentPath = '/' . ltrim(trim($newParentPath, '/') . '/', '/');
339 
340  // Not only sanitize strings, but also remove all dots, to make sure a single dot will work fine as a prefix.title separator.
341  $prefix = ltrim(\Automad\Core\Parse::sanitize($prefix, true) . '.', '.');
342  $title = \Automad\Core\Parse::sanitize($title, true) . '/';
343 
344  // Build new path.
345  $newPath = $newParentPath . $prefix . $title;
346 
347  // Contiune only if old and new paths are different.
348  if ($oldPath != $newPath) {
349 
350  $i = 1;
351 
352  // Check if path exists already
353  while (file_exists(AM_BASE_DIR . AM_DIR_PAGES . $newPath)) {
354 
355  $newPrefix = ltrim(trim($prefix, '.') . '-' . $i, '-') . '.';
356  $newPath = $newParentPath . $newPrefix . $title;
357  $i++;
358 
359  }
360 
361  $old = umask(0);
362 
363  if (!file_exists(AM_BASE_DIR . AM_DIR_PAGES . $newParentPath)) {
364  mkdir(AM_BASE_DIR . AM_DIR_PAGES . $newParentPath, 0777, true);
365  }
366 
367  rename(AM_BASE_DIR . AM_DIR_PAGES . $oldPath, AM_BASE_DIR . AM_DIR_PAGES . $newPath);
368 
369  umask($old);
370 
371  }
372 
373  return $newPath;
374 
375  }
376 
377 
385  private function pageFile($page) {
386 
387  return AM_BASE_DIR . AM_DIR_PAGES . $page->path . $page->template . '.' . AM_FILE_EXT_DATA;
388 
389  }
390 
391 
399  private function passwordHash($password) {
400 
401  $salt = '$2y$10$' . substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 22);
402 
403  return crypt($password, $salt);
404 
405  }
406 
407 
416  private function passwordVerified($password, $hash) {
417 
418  return ($hash === crypt($password, $hash));
419 
420  }
421 
422 
434  private function siteTree($parent, $collection, $parameters, $hideCurrent = false) {
435 
436  $current = \Automad\Core\Parse::queryKey('url');
437 
438  $selection = new \Automad\Core\Selection($collection);
439  $selection->filterByParentUrl($parent);
440  $selection->sortPagesByBasename();
441 
442  if ($pages = $selection->getSelection()) {
443 
444  $html = '<ul class="nav nav-pills nav-stacked pages">';
445 
446  foreach ($pages as $page) {
447 
448  if ($page->url != $current || !$hideCurrent) {
449 
450  if (!$title = basename($page->path)) {
451  $title = '<span class="glyphicon glyphicon-home"></span> Home';
452  }
453 
454  // Check if page is currently selected page
455  if ($page->url == $current) {
456  $html .= '<li class="active"><div class="connector"></div>';
457  } else {
458  $html .= '<li>';
459  }
460 
461  $html .= '<a title="' . basename($page->path) . '" href="?' . http_build_query(array_merge($parameters, array('url' => $page->url)), '', '&amp;') . '">' . $title . '</a>' .
462  $this->siteTree($page->url, $collection, $parameters, $hideCurrent) .
463  '</li>';
464 
465  }
466 
467  }
468 
469  $html .= '</ul>';
470 
471  return $html;
472 
473  }
474 
475  }
476 
477 
484  private function siteName() {
485 
486  return $this->siteData[AM_KEY_SITENAME];
487 
488  }
489 
490 
501  private function templateSelectBox($id = '', $name = '', $selectedTheme = false, $selectedTemplate = false) {
502 
503 
504  // Find all templates of currently used site theme (set in site.txt).
505  $siteThemeTemplates = array_filter(glob(AM_BASE_DIR . AM_DIR_THEMES . '/' . $this->siteData[AM_KEY_THEME] . '/*.php'), function($file) {
506  return false === in_array(basename($file), array(AM_PAGE_NOT_FOUND_TEMPLATE . '.php', AM_PAGE_RESULTS_TEMPLATE . '.php'));
507  });
508 
509  // Find all templates of all installed themes.
510  $templates = array_filter(glob(AM_BASE_DIR . AM_DIR_THEMES . '/*/*.php'), function($file) {
511  return false === in_array(basename($file), array(AM_PAGE_NOT_FOUND_TEMPLATE . '.php', AM_PAGE_RESULTS_TEMPLATE . '.php'));
512  });
513 
514  // Create HTML
515  $html = '<div class="form-group"><label for="' . $id . '">' . $this->tb['page_theme_template'] . '</label><select id="' . $id . '" class="form-control" name="' . $name . '">';
516 
517  // List templates of current sitewide theme
518  foreach($siteThemeTemplates as $template) {
519 
520  $html .= '<option';
521 
522  if (!$selectedTheme && basename($template) === $selectedTemplate . '.php') {
523  $html .= ' selected';
524  }
525 
526  $html .= ' value="' . basename($template) . '">' . ucwords(str_replace(array('_', '.php'), array(' ', ''), basename($template))) . ' (Global Theme)</option>';
527 
528  }
529 
530  // List all found template along with their theme folder
531  foreach($templates as $template) {
532 
533  $html .= '<option';
534 
535  if ($selectedTheme === basename(dirname($template)) && basename($template) === $selectedTemplate . '.php') {
536  $html .= ' selected';
537  }
538 
539  $html .= ' value="' . basename(dirname($template)) . '/' . basename($template) . '">' .
540  ucwords(str_replace('_', ' ', basename(dirname($template)))) . ' Theme > ' . ucwords(str_replace(array('_', '.php'), array(' ', ''), basename($template))) .
541  '</option>';
542  }
543 
544  $html .= '</select></div>';
545 
546  return $html;
547 
548  }
549 
550 
557  private function user() {
558 
559  if (isset($_SESSION['username'])) {
560  return $_SESSION['username'];
561  }
562 
563  }
564 
565 
575  private function varTextArea($key, $value, $removeButton = false) {
576 
577  $html = '<div class="form-group"><label for="input-data-' . $key . '">' . $key . '</label>';
578 
579  if ($removeButton) {
580  $html .= '<button type="button" class="close automad-remove-parent">&times;</button>';
581  }
582 
583  $html .= '<textarea id="input-data-' . $key . '" class="form-control" name="data[' . $key . ']" rows="10">' . $value . '</textarea></div>';
584 
585  return $html;
586 
587  }
588 
589 
590 }
591 
592 
593 ?>
siteTree($parent, $collection, $parameters, $hideCurrent=false)
Definition: gui.php:434
accountsGeneratePHP($accounts)
Definition: gui.php:169
varTextArea($key, $value, $removeButton=false)
Definition: gui.php:575
movePage($oldPath, $newParentPath, $prefix, $title)
Definition: gui.php:335
static siteData()
Definition: parse.php:447
pageFile($page)
Definition: gui.php:385
getSiteVarsInThemes()
Definition: gui.php:290
templateSelectBox($id= '', $name= '', $selectedTheme=false, $selectedTemplate=false)
Definition: gui.php:501
passwordVerified($password, $hash)
Definition: gui.php:416
static sanitize($str, $removeDots=false)
Definition: parse.php:413
static queryKey($key)
Definition: parse.php:294
passwordHash($password)
Definition: gui.php:399
static markdownFile($file)
Definition: parse.php:241