mirror of
https://github.com/typemill/typemill.git
synced 2025-01-17 05:18:19 +01:00
Version 1.3.2: Rename and Hide navigation
This commit is contained in:
parent
00368397ce
commit
53f17927fd
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
cache
|
||||
cache/lastCache.txt
|
||||
content/index.yaml
|
||||
content/00-Welcome/index.yaml
|
||||
content/00-Welcome/00-Setup.yaml
|
||||
|
1
cache/lastCache.txt
vendored
1
cache/lastCache.txt
vendored
@ -1 +0,0 @@
|
||||
1578580890
|
@ -246,9 +246,12 @@ class ContentApiController extends ContentController
|
||||
# update the live structure
|
||||
$this->setStructure($draft = false, $cache = false);
|
||||
|
||||
#update the backend structure
|
||||
# update the backend structure
|
||||
$this->setStructure($draft = true, $cache = false);
|
||||
|
||||
# check if page is in extended structure and delete it
|
||||
$this->deleteFromExtended();
|
||||
|
||||
# dispatch event
|
||||
$this->c->dispatcher->dispatch('onPageDeleted', new OnPageDeleted($this->item));
|
||||
|
||||
@ -324,12 +327,6 @@ class ContentApiController extends ContentController
|
||||
$parentKeyFrom = explode('.', $this->params['parent_id_from']);
|
||||
$parentKeyTo = explode('.', $this->params['parent_id_to']);
|
||||
|
||||
/*
|
||||
echo '<pre>';
|
||||
print_r(array($itemKeyPath 0,$parentKeyFrom navi,$parentKeyTo 2));
|
||||
die();
|
||||
*/
|
||||
|
||||
# get the item from structure
|
||||
$item = Folder::getItemWithKeyPath($this->structure, $itemKeyPath);
|
||||
|
||||
@ -362,10 +359,16 @@ class ContentApiController extends ContentController
|
||||
# delete item from folderContent
|
||||
unset($folderContent[$itemKey]);
|
||||
}
|
||||
elseif($this->params['active'] == 'active')
|
||||
else
|
||||
{
|
||||
# rename links in extended file
|
||||
$this->renameExtended($item, $newFolder);
|
||||
|
||||
# an active file has been moved to another folder, so send new url with response
|
||||
$url = $this->uri->getBaseUrl() . '/tm/content/' . $this->settings['editor'] . $newFolder->urlRelWoF . '/' . $item->slug;
|
||||
if($this->params['active'] == 'active')
|
||||
{
|
||||
$url = $this->uri->getBaseUrl() . '/tm/content/' . $this->settings['editor'] . $newFolder->urlRelWoF . '/' . $item->slug;
|
||||
}
|
||||
}
|
||||
|
||||
# add item to newFolder
|
||||
|
@ -9,6 +9,7 @@ use Typemill\Models\Validation;
|
||||
use Typemill\Models\Folder;
|
||||
use Typemill\Models\Write;
|
||||
use Typemill\Models\WriteCache;
|
||||
use Typemill\Models\WriteYaml;
|
||||
|
||||
abstract class ContentController
|
||||
{
|
||||
@ -182,7 +183,7 @@ abstract class ContentController
|
||||
|
||||
# set variables and objects
|
||||
$this->write = new writeCache();
|
||||
|
||||
|
||||
# check, if cached structure is still valid
|
||||
if($cache && $this->write->validate('cache', 'lastCache.txt', 600))
|
||||
{
|
||||
@ -199,18 +200,76 @@ abstract class ContentController
|
||||
# if there is content, then get the content details
|
||||
if(count($structure) > 0)
|
||||
{
|
||||
# create an array of object with the whole content of the folder
|
||||
$structure = Folder::getFolderContentDetails($structure, $this->uri->getBaseUrl(), $this->uri->getBasePath());
|
||||
# get the extended structure files with changes like navigation title or hidden pages
|
||||
$yaml = new writeYaml();
|
||||
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
|
||||
|
||||
# create an array of object with the whole content of the folder and changes from extended file
|
||||
$structure = Folder::getFolderContentDetails($structure, $extended, $this->uri->getBaseUrl(), $this->uri->getBasePath());
|
||||
}
|
||||
|
||||
# cache navigation
|
||||
$this->write->updateCache('cache', $filename, 'lastCache.txt', $structure);
|
||||
}
|
||||
|
||||
|
||||
$this->structure = $structure;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function renameExtended($item, $newFolder)
|
||||
{
|
||||
# get the extended structure files with changes like navigation title or hidden pages
|
||||
$yaml = new writeYaml();
|
||||
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
|
||||
|
||||
if(isset($extended[$item->urlRelWoF]))
|
||||
{
|
||||
$newUrl = $newFolder->urlRelWoF . '/' . $item->slug;
|
||||
|
||||
$entry = $extended[$item->urlRelWoF];
|
||||
|
||||
unset($extended[$item->urlRelWoF]);
|
||||
|
||||
$extended[$newUrl] = $entry;
|
||||
$yaml->updateYaml('cache', 'structure-extended.yaml', $extended);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function deleteFromExtended()
|
||||
{
|
||||
# get the extended structure files with changes like navigation title or hidden pages
|
||||
$yaml = new writeYaml();
|
||||
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
|
||||
|
||||
if($this->item->elementType == "file" && isset($extended[$this->item->urlRelWoF]))
|
||||
{
|
||||
unset($extended[$this->item->urlRelWoF]);
|
||||
$yaml->updateYaml('cache', 'structure-extended.yaml', $extended);
|
||||
}
|
||||
|
||||
if($this->item->elementType == "folder")
|
||||
{
|
||||
$changed = false;
|
||||
|
||||
# delete all entries with that folder url
|
||||
foreach($extended as $url => $entries)
|
||||
{
|
||||
if( strpos($url, $this->item->urlRelWoF) !== false )
|
||||
{
|
||||
$changed = true;
|
||||
unset($extended[$url]);
|
||||
}
|
||||
}
|
||||
|
||||
if($changed)
|
||||
{
|
||||
$yaml->updateYaml('cache', 'structure-extended.yaml', $extended);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function setHomepage()
|
||||
{
|
||||
$contentFolder = Folder::scanFolderFlat($this->settings['rootPath'] . $this->settings['contentFolder']);
|
||||
@ -251,6 +310,7 @@ abstract class ContentController
|
||||
}
|
||||
|
||||
$this->errors = ['errors' => ['message' => 'requested page-url not found']];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -334,6 +394,9 @@ abstract class ContentController
|
||||
}
|
||||
return rmdir($path);
|
||||
}
|
||||
|
||||
# delete all files from the extended file
|
||||
$this->deleteFromExtended();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace Typemill\Controllers;
|
||||
use Slim\Http\Request;
|
||||
use Slim\Http\Response;
|
||||
use Typemill\Models\WriteYaml;
|
||||
use Typemill\Models\Folder;
|
||||
|
||||
class MetaApiController extends ContentController
|
||||
{
|
||||
@ -23,10 +24,6 @@ class MetaApiController extends ContentController
|
||||
|
||||
$metatabs = $writeYaml->getYaml('system' . DIRECTORY_SEPARATOR . 'author', 'metatabs.yaml');
|
||||
|
||||
# load cached metadefinitions
|
||||
# check if valid
|
||||
# if not, refresh cache
|
||||
|
||||
# loop through all plugins
|
||||
foreach($this->settings['plugins'] as $name => $plugin)
|
||||
{
|
||||
@ -39,6 +36,14 @@ class MetaApiController extends ContentController
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# add the meta from theme settings here
|
||||
$themeSettings = \Typemill\Settings::getObjectSettings('themes', $this->settings['theme']);
|
||||
|
||||
if($themeSettings && isset($themeSettings['metatabs']))
|
||||
{
|
||||
$metatabs = array_merge_recursive($metatabs, $themeSettings['metatabs']);
|
||||
}
|
||||
|
||||
return $metatabs;
|
||||
}
|
||||
@ -77,32 +82,37 @@ class MetaApiController extends ContentController
|
||||
$metadefinitions = $this->aggregateMetaDefinitions();
|
||||
|
||||
$metadata = [];
|
||||
$metascheme = [];
|
||||
|
||||
foreach($metadefinitions as $tabname => $tab )
|
||||
{
|
||||
$metadata[$tabname] = [];
|
||||
$metadata[$tabname] = [];
|
||||
|
||||
foreach($tab['fields'] as $fieldname => $fielddefinitions)
|
||||
{
|
||||
$metascheme[$tabname][$fieldname] = true;
|
||||
$metadata[$tabname][$fieldname] = isset($pagemeta[$tabname][$fieldname]) ? $pagemeta[$tabname][$fieldname] : null;
|
||||
}
|
||||
}
|
||||
|
||||
# store the metascheme in cache for frontend
|
||||
$writeYaml->updateYaml('cache', 'metatabs.yaml', $metascheme);
|
||||
|
||||
return $response->withJson(array('metadata' => $metadata, 'metadefinitions' => $metadefinitions, 'errors' => false));
|
||||
}
|
||||
|
||||
public function updateArticleMeta(Request $request, Response $response, $args)
|
||||
{
|
||||
/* get params from call */
|
||||
# get params from call
|
||||
$this->params = $request->getParams();
|
||||
$this->uri = $request->getUri();
|
||||
|
||||
$tab = isset($this->params['tab']) ? $this->params['tab'] : false;
|
||||
$metaData = isset($this->params['data']) ? $this->params['data'] : false ;
|
||||
$metaInput = isset($this->params['data']) ? $this->params['data'] : false ;
|
||||
$objectName = 'meta';
|
||||
$errors = false;
|
||||
|
||||
if(!$tab or !$metaData)
|
||||
if(!$tab or !$metaInput)
|
||||
{
|
||||
return $response->withJson($this->errors, 404);
|
||||
}
|
||||
@ -114,7 +124,7 @@ class MetaApiController extends ContentController
|
||||
$validate = $this->getValidator();
|
||||
|
||||
# take the user input data and iterate over all fields and values
|
||||
foreach($metaData as $fieldName => $fieldValue)
|
||||
foreach($metaInput as $fieldName => $fieldValue)
|
||||
{
|
||||
# get the corresponding field definition from original plugin settings */
|
||||
$fieldDefinition = isset($metaDefinitions[$tab]['fields'][$fieldName]) ? $metaDefinitions[$tab]['fields'][$fieldName] : false;
|
||||
@ -147,16 +157,66 @@ class MetaApiController extends ContentController
|
||||
$writeYaml = new writeYaml();
|
||||
|
||||
# get existing metadata for page
|
||||
$meta = $writeYaml->getYaml($this->settings['contentFolder'], $this->item->pathWithoutType . '.yaml');
|
||||
$metaPage = $writeYaml->getYaml($this->settings['contentFolder'], $this->item->pathWithoutType . '.yaml');
|
||||
|
||||
# get extended structure
|
||||
$extended = $writeYaml->getYaml('cache', 'structure-extended.yaml');
|
||||
|
||||
# flag for changed structure
|
||||
$structure = false;
|
||||
|
||||
if($tab == 'meta')
|
||||
{
|
||||
# normalize the meta-input
|
||||
$metaInput['navtitle'] = (isset($metaInput['navtitle']) && $metaInput['navtitle'] !== null )? $metaInput['navtitle'] : '';
|
||||
$metaInput['hide'] = (isset($metaInput['hide']) && $metaInput['hide'] !== null) ? $metaInput['hide'] : false;
|
||||
|
||||
# input values are empty but entry in structure exists
|
||||
if(!$metaInput['hide'] && $metaInput['navtitle'] == "" && isset($extended[$this->item->urlRelWoF]))
|
||||
{
|
||||
# delete the entry in the structure
|
||||
unset($extended[$this->item->urlRelWoF]);
|
||||
|
||||
$structure = true;
|
||||
}
|
||||
|
||||
# check if navtitle or hide-value has been changed
|
||||
elseif(
|
||||
($metaPage['meta']['navtitle'] != $metaInput['navtitle'])
|
||||
OR
|
||||
($metaPage['meta']['hide'] != $metaInput['hide'])
|
||||
)
|
||||
{
|
||||
# add new file data. Also makes sure that the value is set.
|
||||
$extended[$this->item->urlRelWoF] = ['hide' => $metaInput['hide'], 'navtitle' => $metaInput['navtitle']];
|
||||
|
||||
$structure = true;
|
||||
}
|
||||
|
||||
if($structure)
|
||||
{
|
||||
# store the file
|
||||
$writeYaml->updateYaml('cache', 'structure-extended.yaml', $extended);
|
||||
|
||||
# recreate the draft structure
|
||||
$this->setStructure($draft = true, $cache = false);
|
||||
|
||||
# set item in navigation active again
|
||||
$activeItem = Folder::getItemForUrl($this->structure, $this->item->urlRel, $this->uri->getBaseUrl());
|
||||
|
||||
# send new structure to frontend
|
||||
$structure = $this->structure;
|
||||
}
|
||||
}
|
||||
|
||||
# add the new/edited metadata
|
||||
$meta[$tab] = $metaData;
|
||||
$meta[$tab] = $metaInput;
|
||||
|
||||
# store the metadata
|
||||
$writeYaml->updateYaml($this->settings['contentFolder'], $this->item->pathWithoutType . '.yaml', $meta);
|
||||
|
||||
# return with the new metadata
|
||||
return $response->withJson(array('metadata' => $metaData, 'errors' => false));
|
||||
return $response->withJson(array('metadata' => $metaInput, 'structure' => $structure, 'errors' => false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ class PageController extends Controller
|
||||
try
|
||||
{
|
||||
/* if the cached structure is still valid, use it */
|
||||
if($cache->validate('cache', 'lastCache.txt',600))
|
||||
if($cache->validate('cache', 'lastCache.txt', 600))
|
||||
{
|
||||
$structure = $this->getCachedStructure($cache);
|
||||
}
|
||||
@ -75,7 +75,15 @@ class PageController extends Controller
|
||||
echo $e->getMessage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
# get the cached navigation here (structure without hidden files )
|
||||
$navigation = $cache->getCache('cache', 'navigation.txt');
|
||||
if(!$navigation)
|
||||
{
|
||||
# use the structure as navigation if there is no difference
|
||||
$navigation = $structure;
|
||||
}
|
||||
|
||||
# if the user is on startpage
|
||||
if(empty($args))
|
||||
{
|
||||
@ -93,7 +101,7 @@ class PageController extends Controller
|
||||
/* if there is still no item, return a 404-page */
|
||||
if(!$item)
|
||||
{
|
||||
return $this->render404($response, array( 'navigation' => $structure, 'settings' => $settings, 'base_url' => $base_url ));
|
||||
return $this->render404($response, array( 'navigation' => $navigation, 'settings' => $settings, 'base_url' => $base_url ));
|
||||
}
|
||||
|
||||
/* get breadcrumb for page */
|
||||
@ -124,7 +132,6 @@ class PageController extends Controller
|
||||
|
||||
# get meta-Information
|
||||
$writeYaml = new WriteYaml();
|
||||
|
||||
$metatabs = $writeYaml->getPageMeta($settings, $item);
|
||||
|
||||
if(!$metatabs)
|
||||
@ -196,12 +203,19 @@ class PageController extends Controller
|
||||
$theme = $settings['theme'];
|
||||
$route = empty($args) && isset($settings['themes'][$theme]['cover']) ? '/cover.twig' : '/index.twig';
|
||||
|
||||
# check if there is a custom theme css
|
||||
$customcss = $writeYaml->checkFile('cache', $theme . '-custom.css');
|
||||
if($customcss)
|
||||
{
|
||||
$this->c->assets->addCSS($base_url . '/cache/' . $theme . '-custom.css');
|
||||
}
|
||||
|
||||
return $this->render($response, $route, [
|
||||
'home' => $home,
|
||||
'navigation' => $structure,
|
||||
'title' => $title,
|
||||
'navigation' => $navigation,
|
||||
'title' => $title,
|
||||
'content' => $contentHTML,
|
||||
'item' => $item,
|
||||
'item' => $item,
|
||||
'breadcrumb' => $breadcrumb,
|
||||
'settings' => $settings,
|
||||
'metatabs' => $metatabs,
|
||||
@ -225,15 +239,62 @@ class PageController extends Controller
|
||||
return false;
|
||||
}
|
||||
|
||||
/* create an array of object with the whole content of the folder */
|
||||
$structure = Folder::getFolderContentDetails($structure, $uri->getBaseUrl(), $uri->getBasePath());
|
||||
# get the extended structure files with changes like navigation title or hidden pages
|
||||
$yaml = new writeYaml();
|
||||
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
|
||||
|
||||
/* cache navigation */
|
||||
/* create an array of object with the whole content of the folder */
|
||||
$structure = Folder::getFolderContentDetails($structure, $extended, $uri->getBaseUrl(), $uri->getBasePath());
|
||||
|
||||
/* cache structure */
|
||||
$cache->updateCache('cache', 'structure.txt', 'lastCache.txt', $structure);
|
||||
|
||||
if($this->containsHiddenPages($extended))
|
||||
{
|
||||
# generate the navigation (delete empty pages)
|
||||
$navigation = $this->createNavigationFromStructure($structure);
|
||||
|
||||
# cache navigation
|
||||
$cache->updateCache('cache', 'navigation.txt', false, $navigation);
|
||||
}
|
||||
else
|
||||
{
|
||||
# make sure no separate navigation file is set
|
||||
$cache->deleteFileWithPath('cache' . DIRECTORY_SEPARATOR . 'navigation.txt');
|
||||
}
|
||||
|
||||
return $structure;
|
||||
}
|
||||
|
||||
protected function containsHiddenPages($extended)
|
||||
{
|
||||
foreach($extended as $element)
|
||||
{
|
||||
if(isset($element['hide']) && $element['hide'] === true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function createNavigationFromStructure($navigation)
|
||||
{
|
||||
foreach ($navigation as $key => $element)
|
||||
{
|
||||
if($element->hide === true)
|
||||
{
|
||||
unset($navigation[$key]);
|
||||
}
|
||||
elseif(isset($element->folderContent))
|
||||
{
|
||||
$navigation[$key]->folderContent = $this->createNavigationFromStructure($element->folderContent);
|
||||
}
|
||||
}
|
||||
|
||||
return $navigation;
|
||||
}
|
||||
|
||||
protected function updateVersion($baseUrl)
|
||||
{
|
||||
/* check the latest public typemill version */
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace Typemill\Controllers;
|
||||
|
||||
use \Symfony\Component\Yaml\Yaml;
|
||||
use Typemill\Models\Write;
|
||||
use Typemill\Models\Fields;
|
||||
use Typemill\Models\Validation;
|
||||
use Typemill\Models\User;
|
||||
@ -91,7 +92,7 @@ class SettingsController extends Controller
|
||||
|
||||
public function showThemes($request, $response, $args)
|
||||
{
|
||||
$userSettings = $this->c->get('settings');
|
||||
$userSettings = $this->c->get('settings');
|
||||
$themes = $this->getThemes();
|
||||
$themedata = array();
|
||||
$fieldsModel = new Fields();
|
||||
@ -109,24 +110,40 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
$themeSettings = \Typemill\Settings::getObjectSettings('themes', $themeName);
|
||||
|
||||
# add standard-textarea for custom css
|
||||
$themeSettings['forms']['fields']['customcss'] = ['type' => 'textarea', 'label' => 'Custom CSS', 'rows' => 10, 'class' => 'codearea', 'description' => 'You can overwrite the theme-css with your own css here.'];
|
||||
|
||||
# load custom css-file
|
||||
$write = new write();
|
||||
$customcss = $write->getFile('cache', $themeName . '-custom.css');
|
||||
$themeSettings['settings']['customcss'] = $customcss;
|
||||
|
||||
|
||||
if($themeSettings)
|
||||
{
|
||||
/* store them as default theme data with author, year, default settings and field-definitions */
|
||||
$themedata[$themeName] = $themeSettings;
|
||||
}
|
||||
|
||||
|
||||
if(isset($themeSettings['forms']['fields']))
|
||||
{
|
||||
$fields = $fieldsModel->getFields($userSettings, 'themes', $themeName, $themeSettings);
|
||||
|
||||
$fields = $fieldsModel->getFields($userSettings, 'themes', $themeName, $themeSettings);
|
||||
|
||||
/* overwrite original theme form definitions with enhanced form objects */
|
||||
$themedata[$themeName]['forms']['fields'] = $fields;
|
||||
}
|
||||
|
||||
/* add the preview image */
|
||||
$img = getcwd() . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeName . DIRECTORY_SEPARATOR . $themeName . '.jpg';
|
||||
$img = file_exists($img) ? $img : false;
|
||||
|
||||
$img = getcwd() . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeName . DIRECTORY_SEPARATOR . $themeName;
|
||||
$jpg = $img . '.jpg';
|
||||
$png = $img . '.png';
|
||||
$img = file_exists($jpg) ? $jpg : false;
|
||||
if(!$img)
|
||||
{
|
||||
$img = file_exists($png) ? $png : false;
|
||||
}
|
||||
|
||||
$themedata[$themeName]['img'] = $img;
|
||||
}
|
||||
|
||||
@ -134,7 +151,7 @@ class SettingsController extends Controller
|
||||
$user = new User();
|
||||
$users = $user->getUsers();
|
||||
$route = $request->getAttribute('route');
|
||||
|
||||
|
||||
return $this->render($response, 'settings/themes.twig', array('settings' => $userSettings, 'themes' => $themedata, 'users' => $users, 'route' => $route->getName() ));
|
||||
}
|
||||
|
||||
@ -245,6 +262,34 @@ class SettingsController extends Controller
|
||||
/* set theme name and delete theme settings from user settings for the case, that the new theme has no settings */
|
||||
$userSettings['theme'] = $themeName;
|
||||
|
||||
# extract the custom css from user input
|
||||
$customcss = isset($userInput['customcss']) ? $userInput['customcss'] : false;
|
||||
|
||||
# delete custom css from userinput
|
||||
unset($userInput['customcss']);
|
||||
|
||||
$write = new write();
|
||||
|
||||
# make sure no file is set if there is no custom css
|
||||
if(!$customcss OR $customcss == '')
|
||||
{
|
||||
# delete the css file if exists
|
||||
$write->deleteFileWithPath('cache' . DIRECTORY_SEPARATOR . $themeName . '-custom.css');
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $customcss != strip_tags($customcss) )
|
||||
{
|
||||
$_SESSION['errors'][$themeName]['customcss'][] = 'custom css contains html';
|
||||
}
|
||||
else
|
||||
{
|
||||
# store css
|
||||
$write = new write();
|
||||
$write->writeFile('cache', $themeName . '-custom.css', $customcss);
|
||||
}
|
||||
}
|
||||
|
||||
if($userInput)
|
||||
{
|
||||
/* validate the user-input */
|
||||
|
@ -16,7 +16,7 @@ class Folder
|
||||
{
|
||||
$folderItems = scandir($folderPath);
|
||||
$folderContent = array();
|
||||
|
||||
|
||||
foreach ($folderItems as $key => $item)
|
||||
{
|
||||
if (!in_array($item, array(".","..")))
|
||||
@ -96,8 +96,8 @@ class Folder
|
||||
* vars: multidimensional array with folder- and file-names
|
||||
* returns: array of objects. Each object contains information about an item (file or folder).
|
||||
*/
|
||||
public static function getFolderContentDetails(array $folderContent, $baseUrl, $fullSlugWithFolder = NULL, $fullSlugWithoutFolder = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
|
||||
{
|
||||
public static function getFolderContentDetails(array $folderContent, $extended, $baseUrl, $fullSlugWithFolder = NULL, $fullSlugWithoutFolder = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
|
||||
{
|
||||
$contentDetails = [];
|
||||
$iteration = 0;
|
||||
$chapternr = 1;
|
||||
@ -147,8 +147,16 @@ class Folder
|
||||
$item->chapter = $chapter ? $chapter . '.' . $chapternr : $chapternr;
|
||||
$item->active = false;
|
||||
$item->activeParent = false;
|
||||
$item->hide = false;
|
||||
|
||||
$item->folderContent = self::getFolderContentDetails($name, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter);
|
||||
# check if there are extended information
|
||||
if($extended && isset($extended[$item->urlRelWoF]))
|
||||
{
|
||||
$item->name = ($extended[$item->urlRelWoF]['navtitle'] != '') ? $extended[$item->urlRelWoF]['navtitle'] : $item->name;
|
||||
$item->hide = ($extended[$item->urlRelWoF]['hide'] === true) ? true : false;
|
||||
}
|
||||
|
||||
$item->folderContent = self::getFolderContentDetails($name, $extended, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -196,6 +204,14 @@ class Folder
|
||||
$item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
$item->active = false;
|
||||
$item->activeParent = false;
|
||||
$item->hide = false;
|
||||
|
||||
# check if there are extended information
|
||||
if($extended && isset($extended[$item->urlRelWoF]))
|
||||
{
|
||||
$item->name = ($extended[$item->urlRelWoF]['navtitle'] != '') ? $extended[$item->urlRelWoF]['navtitle'] : $item->name;
|
||||
$item->hide = ($extended[$item->urlRelWoF]['hide'] === true) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
$iteration++;
|
||||
@ -223,9 +239,9 @@ class Folder
|
||||
|
||||
foreach($folderContentDetails as $key => $item)
|
||||
{
|
||||
# set item active, needed to move item in navigation
|
||||
if($item->urlRel === $url)
|
||||
{
|
||||
# set item active, needed for move item in navigation
|
||||
$item->active = true;
|
||||
$result = $item;
|
||||
}
|
||||
@ -234,6 +250,7 @@ class Folder
|
||||
$result = self::getItemForUrl($item->folderContent, $url, $baseUrl, $result);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -378,6 +395,30 @@ class Folder
|
||||
|
||||
return array('structure' => $structure, 'item' => $item);
|
||||
}
|
||||
|
||||
# NOT IN USE
|
||||
public static function deleteItemWithKeyPath($structure, array $keys)
|
||||
{
|
||||
$result = &$structure;
|
||||
$last = array_pop($keys);
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if(isset($result[$key]->folderContent))
|
||||
{
|
||||
$result = &$result[$key]->folderContent;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = &$result[$key];
|
||||
}
|
||||
}
|
||||
|
||||
$item = $result[$last];
|
||||
unset($result[$last]);
|
||||
|
||||
return $structure;
|
||||
}
|
||||
|
||||
/* get breadcrumb as copied array, set elements active in original and mark parent element in original */
|
||||
public static function getBreadcrumb($content, $searchArray, $i = NULL, $breadcrumb = NULL)
|
||||
|
@ -23,6 +23,5 @@ class Helpers{
|
||||
}
|
||||
$table .= '</table></body></html>';
|
||||
echo $table;
|
||||
exit;
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ class Write
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkFile($folder, $file)
|
||||
public function checkFile($folder, $file)
|
||||
{
|
||||
if(!file_exists($this->basePath . $folder . DIRECTORY_SEPARATOR . $file))
|
||||
{
|
||||
@ -50,7 +50,7 @@ class Write
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkFileWithPath($filepath)
|
||||
public function checkFileWithPath($filepath)
|
||||
{
|
||||
if(!file_exists($this->basePath . $filepath))
|
||||
{
|
||||
@ -62,7 +62,7 @@ class Write
|
||||
public function writeFile($folder, $file, $data)
|
||||
{
|
||||
if($this->checkPath($folder))
|
||||
{
|
||||
{
|
||||
$filePath = $this->basePath . $folder . DIRECTORY_SEPARATOR . $file;
|
||||
|
||||
$openFile = @fopen($filePath, "w");
|
||||
@ -70,11 +70,11 @@ class Write
|
||||
if(!$openFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fwrite($openFile, $data);
|
||||
fclose($openFile);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -118,8 +118,10 @@ class Write
|
||||
$newOrder = ($index < 10) ? '0' . $index : $index;
|
||||
|
||||
# create new path with foldername or filename but without file-type
|
||||
$newPath = $this->basePath . 'content' . $folderPath . DIRECTORY_SEPARATOR . $newOrder . '-' . str_replace(" ", "-", $item->name);
|
||||
# $newPath = $this->basePath . 'content' . $folderPath . DIRECTORY_SEPARATOR . $newOrder . '-' . str_replace(" ", "-", $item->name);
|
||||
|
||||
$newPath = $this->basePath . 'content' . $folderPath . DIRECTORY_SEPARATOR . $newOrder . '-' . $item->slug;
|
||||
|
||||
if($item->elementType == 'folder')
|
||||
{
|
||||
$oldPath = $this->basePath . 'content' . $item->path;
|
||||
|
@ -10,7 +10,7 @@ class WriteCache extends Write
|
||||
* @return boolean for an invalid cache (false) and for a valid cache (true).
|
||||
*/
|
||||
public function validate($folderName, $fileName, $duration)
|
||||
{
|
||||
{
|
||||
if(isset($_SERVER['HTTP_CACHE_CONTROL']) && $_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0')
|
||||
{
|
||||
return false;
|
||||
@ -28,7 +28,7 @@ class WriteCache extends Write
|
||||
}
|
||||
|
||||
$lastRefresh = file_get_contents($folderName . DIRECTORY_SEPARATOR . $fileName);
|
||||
|
||||
|
||||
if(time() - $lastRefresh > $duration)
|
||||
{
|
||||
return false;
|
||||
|
@ -48,6 +48,14 @@ class WriteYaml extends Write
|
||||
return false;
|
||||
}
|
||||
|
||||
# compare with meta that are in use right now (e.g. changed theme, disabled plugin)
|
||||
$metascheme = $this->getYaml('cache', 'metatabs.yaml');
|
||||
|
||||
if($metascheme)
|
||||
{
|
||||
$meta = $this->whitelistMeta($meta,$metascheme);
|
||||
}
|
||||
|
||||
$meta = $this->addFileTimeToMeta($meta, $item, $settings);
|
||||
|
||||
return $meta;
|
||||
@ -117,6 +125,27 @@ class WriteYaml extends Write
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
private function whitelistMeta($meta, $metascheme)
|
||||
{
|
||||
# we have only 2 dimensions, so no recursive needed
|
||||
foreach($meta as $tab => $values)
|
||||
{
|
||||
if(!isset($metascheme[$tab]))
|
||||
{
|
||||
unset($meta[$tab]);
|
||||
}
|
||||
foreach($values as $key => $value)
|
||||
{
|
||||
if(!isset($metascheme[$tab][$key]))
|
||||
{
|
||||
unset($meta[$tab][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
private function addFileTimeToMeta($meta, $item, $settings)
|
||||
{
|
||||
$filePath = $settings['contentFolder'] . $item->path;
|
||||
|
@ -16,11 +16,10 @@ class Settings
|
||||
$settings = array_merge($defaultSettings, $userSettings);
|
||||
}
|
||||
|
||||
// i18n
|
||||
// load the strings of the set language
|
||||
$language = $settings['language'];
|
||||
$settings['labels'] = self::getLanguageLabels($language);
|
||||
|
||||
# i18n
|
||||
# load the strings of the set language
|
||||
$language = $settings['language'];
|
||||
$settings['labels'] = self::getLanguageLabels($language);
|
||||
|
||||
# We know the used theme now so create the theme path
|
||||
$settings['themePath'] = $settings['rootPath'] . $settings['themeFolder'] . DIRECTORY_SEPARATOR . $settings['theme'];
|
||||
@ -77,15 +76,16 @@ class Settings
|
||||
}
|
||||
|
||||
|
||||
// i18n
|
||||
public static function getLanguageLabels($language)
|
||||
# i18n
|
||||
public static function getLanguageLabels($language)
|
||||
{
|
||||
// if not present, set the English language
|
||||
if( empty($language) ){
|
||||
$language = 'en';
|
||||
}
|
||||
# if not present, set the English language
|
||||
if( empty($language) )
|
||||
{
|
||||
$language = 'en';
|
||||
}
|
||||
|
||||
// load the strings of the set language
|
||||
# load the strings of the set language
|
||||
$yaml = new Models\WriteYaml();
|
||||
$labels = $yaml->getYaml('settings/languages', $language.'.yaml');
|
||||
|
||||
@ -124,7 +124,7 @@ class Settings
|
||||
if($userSettings)
|
||||
{
|
||||
# whitelist settings that can be stored in usersettings (values are not relevant here, only keys)
|
||||
$allowedUserSettings = ['displayErrorDetails' => false,
|
||||
$allowedUserSettings = ['displayErrorDetails' => true,
|
||||
'title' => false,
|
||||
'copyright' => false,
|
||||
'language' => false,
|
||||
@ -151,7 +151,7 @@ class Settings
|
||||
# merge usersettings with new settings
|
||||
$settings = array_merge($userSettings, $settings);
|
||||
|
||||
/* write settings to yaml */
|
||||
# write settings to yaml
|
||||
$yaml = new Models\WriteYaml();
|
||||
$yaml->updateYaml('settings', 'settings.yaml', $settings);
|
||||
}
|
||||
|
@ -411,7 +411,6 @@ footer{
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* OPEN-CLOSE BUTTON *
|
||||
************************/
|
||||
@ -972,6 +971,15 @@ ul.cardInfo{
|
||||
.cardField input, .cardField select, .cardField textarea{
|
||||
background-color: #FFF;
|
||||
}
|
||||
textarea.codearea, .cardField textarea.codearea{
|
||||
font-family: monospace;
|
||||
background: #333;
|
||||
color: #fff;
|
||||
}
|
||||
textarea.codearea:focus, .cardField textarea.codearea:focus{
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.cardFields fieldset.subfield{
|
||||
padding: 20px;
|
||||
border: 1px solid #ddd;
|
||||
@ -1018,7 +1026,7 @@ span.error{
|
||||
line-height: 1em;
|
||||
}
|
||||
.cardInner span.error{
|
||||
display: block;
|
||||
display: inline-block;
|
||||
margin-top: -8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
@ -439,6 +439,10 @@ let meta = new Vue({
|
||||
.then(function (response) {
|
||||
self.saved = true;
|
||||
self.formErrors = self.formErrorsReset;
|
||||
if(response.data.structure)
|
||||
{
|
||||
navi.items = response.data.structure;
|
||||
}
|
||||
})
|
||||
.catch(function (error)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
const navcomponent = Vue.component('navigation', {
|
||||
template: '#navigation-template',
|
||||
props: ['homepage', 'showForm', 'name', 'newItem', 'parent', 'active', 'filetype', 'status', 'elementtype', 'element', 'folder', 'level', 'url', 'root', 'freeze'],
|
||||
props: ['homepage', 'showForm', 'name', 'hide', 'newItem', 'parent', 'active', 'filetype', 'status', 'elementtype', 'element', 'folder', 'level', 'url', 'root', 'freeze'],
|
||||
data: function () {
|
||||
return {
|
||||
showForm: false,
|
||||
@ -88,8 +88,12 @@ const navcomponent = Vue.component('navigation', {
|
||||
level = level.split('.').length;
|
||||
return 'level-' + level;
|
||||
},
|
||||
getIcon : function(elementtype, filetype)
|
||||
getIcon : function(elementtype, filetype, hide)
|
||||
{
|
||||
if(hide)
|
||||
{
|
||||
return '#icon-eye-blocked';
|
||||
}
|
||||
if(elementtype == 'file')
|
||||
{
|
||||
return '#icon-file-text-o';
|
||||
@ -99,8 +103,12 @@ const navcomponent = Vue.component('navigation', {
|
||||
return '#icon-folder-o';
|
||||
}
|
||||
},
|
||||
getIconClass : function(elementtype, filetype)
|
||||
getIconClass : function(elementtype, filetype, hide)
|
||||
{
|
||||
if(hide)
|
||||
{
|
||||
return 'icon-eye-blocked ' + filetype;
|
||||
}
|
||||
if(elementtype == 'file')
|
||||
{
|
||||
return 'icon-file-text-o ' + filetype;
|
||||
|
@ -142,6 +142,12 @@
|
||||
<title>cross</title>
|
||||
<path d="M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-eye-blocked" viewBox="0 0 32 32">
|
||||
<title>eye-blocked</title>
|
||||
<path d="M29.561 0.439c-0.586-0.586-1.535-0.586-2.121 0l-6.318 6.318c-1.623-0.492-3.342-0.757-5.122-0.757-6.979 0-13.028 4.064-16 10 1.285 2.566 3.145 4.782 5.407 6.472l-4.968 4.968c-0.586 0.586-0.586 1.535 0 2.121 0.293 0.293 0.677 0.439 1.061 0.439s0.768-0.146 1.061-0.439l27-27c0.586-0.586 0.586-1.536 0-2.121zM13 10c1.32 0 2.44 0.853 2.841 2.037l-3.804 3.804c-1.184-0.401-2.037-1.521-2.037-2.841 0-1.657 1.343-3 3-3zM3.441 16c1.197-1.891 2.79-3.498 4.67-4.697 0.122-0.078 0.246-0.154 0.371-0.228-0.311 0.854-0.482 1.776-0.482 2.737 0 1.715 0.54 3.304 1.459 4.607l-1.904 1.904c-1.639-1.151-3.038-2.621-4.114-4.323z"></path>
|
||||
<path d="M24 13.813c0-0.849-0.133-1.667-0.378-2.434l-10.056 10.056c0.768 0.245 1.586 0.378 2.435 0.378 4.418 0 8-3.582 8-8z"></path>
|
||||
<path d="M25.938 9.062l-2.168 2.168c0.040 0.025 0.079 0.049 0.118 0.074 1.88 1.199 3.473 2.805 4.67 4.697-1.197 1.891-2.79 3.498-4.67 4.697-2.362 1.507-5.090 2.303-7.889 2.303-1.208 0-2.403-0.149-3.561-0.439l-2.403 2.403c1.866 0.671 3.873 1.036 5.964 1.036 6.978 0 13.027-4.064 16-10-1.407-2.81-3.504-5.2-6.062-6.938z"></path>
|
||||
</symbol>
|
||||
{{ assets.renderSvg() }}
|
||||
</defs>
|
||||
</svg>
|
||||
|
@ -29,4 +29,33 @@ meta:
|
||||
type: date
|
||||
label: Created at (readonly)
|
||||
readonly: readonly
|
||||
class: medium
|
||||
class: medium
|
||||
navtitle:
|
||||
type: text
|
||||
label: Navigation Title
|
||||
class: medium
|
||||
maxlength: 60
|
||||
hide:
|
||||
type: checkbox
|
||||
label: Hide
|
||||
checkboxlabel: Hide page from navigation
|
||||
class: medium
|
||||
# roles:
|
||||
# type: select
|
||||
# label: Show page to
|
||||
# class: medium
|
||||
# options:
|
||||
# null: null
|
||||
# public: Public (standard)
|
||||
# members: Members only (logged in)
|
||||
# customers: Customers only (paying)
|
||||
# list:
|
||||
# type: select
|
||||
# label: List sub-pages
|
||||
# class: medium
|
||||
# options:
|
||||
# null: null
|
||||
# standard: Standard order
|
||||
# revert: Reverse order
|
||||
# asc: Date ascending
|
||||
# desc: Date descending
|
@ -20,11 +20,12 @@
|
||||
v-for="item in items"
|
||||
ref="draggit"
|
||||
:freeze="freeze"
|
||||
:name="item.name"
|
||||
:name="item.name"
|
||||
:hide="item.hide"
|
||||
:active="item.active"
|
||||
:parent="item.activeParent"
|
||||
:level="item.keyPath"
|
||||
:root="root"
|
||||
:level="item.keyPath"
|
||||
:root="root"
|
||||
:url="item.urlRelWoF"
|
||||
:id="item.keyPath"
|
||||
:key="item.keyPath"
|
||||
@ -57,7 +58,7 @@
|
||||
<template id="navigation-template">
|
||||
<li class="navi-item" :class="elementtype">
|
||||
<div class="status" :class="status"></div>
|
||||
<a v-bind:href="getUrl(root, url)" :class="checkActive(active,parent)"><span class="iconwrapper"><svg class="icon" :class="getIconClass(elementtype, filetype)"><use :xlink:href="getIcon(elementtype, filetype)"></use></svg></span><span :class="getLevel(level)">{{ name }}</span><span class="movewrapper"><span class="movewrapper"><svg class="icon icon-arrows-v"><use xlink:href="#icon-arrows-v"></use></svg></span></a>
|
||||
<a v-bind:href="getUrl(root, url)" :class="checkActive(active,parent)"><span class="iconwrapper"><svg class="icon" :class="getIconClass(elementtype, filetype, hide)"><use :xlink:href="getIcon(elementtype, filetype, hide)"></use></svg></span><span :class="getLevel(level)">{{ name }}</span><span class="movewrapper"><span class="movewrapper"><svg class="icon icon-arrows-v"><use xlink:href="#icon-arrows-v"></use></svg></span></a>
|
||||
<draggable v-if="folder" class="navi-list" tag="ul"
|
||||
@start="onStart"
|
||||
@end="onEnd"
|
||||
@ -71,6 +72,7 @@
|
||||
ref="draggit"
|
||||
:freeze="freeze"
|
||||
:name="item.name"
|
||||
:hide="item.hide"
|
||||
:active="item.active"
|
||||
:parent="item.activeParent"
|
||||
:level="item.keyPath"
|
||||
|
@ -9,7 +9,7 @@
|
||||
{{ content }}
|
||||
|
||||
<div class="actionLink">
|
||||
<a href="{{ navigation[0].urlRel }}">{{ settings.themes.typemill.start ? __(settings.themes.typemill.start) : __('Start')}}</a>
|
||||
<a href="{{ navigation[0].urlRel }}">{{ settings.themes.typemill.start ? settings.themes.typemill.start : __('Start')}}</a>
|
||||
|
||||
{% if settings.setup %}
|
||||
<a href="{{ base_url }}/setup">{{ __('Setup') }}</a>
|
||||
|
@ -1,5 +1,5 @@
|
||||
name: Typemill Theme
|
||||
version: 1.2.1
|
||||
version: 1.2.2
|
||||
description: The standard theme for Typemill. Responsive, minimal and without any dependencies. It uses the system fonts Calibri and Helvetica. No JavaScript is used.
|
||||
author: Sebastian Schürmanns
|
||||
homepage: https://typemill.net
|
||||
|
Loading…
x
Reference in New Issue
Block a user