1
0
mirror of https://github.com/typemill/typemill.git synced 2025-07-23 07:11:17 +02:00

Assets and general cleanup for dev-release

This commit is contained in:
trendschau
2023-08-01 22:08:19 +02:00
parent dd28d8a5ec
commit 73c5fe0fc9
29 changed files with 175 additions and 1768 deletions

1
cache/index.json vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -39,19 +39,19 @@ Biig blocks:
Small features:
* DONE: Merge processAssets modell
* DONE: Table of content duplicated for published pages
* DONE: Session handling: csrf fail and session start error if restrictions are active
* DONE: Image and files for meta
* Backend fields
* Proxy
* Editor: Warn if open another block
* Image generation on the fly
* Assets
* Bug: Navigation frontend if unpublished pages
* Sitemap and ping
* Captcha
* Clear Cache
* Security Log
* Backend fields
* Proxy
* DONE: Session handling: csrf fail and session start error if restrictions are active
* Editor: Warn if open another block
* Image generation on the fly
* Assets
* Bug: Table of content duplicated for published pages
* Bug: Navigation frontend if unpublished pages
* Image and files for meta
Cleanups:

View File

@@ -0,0 +1 @@
["# ToDos Version 2","[TOC]","## Visual Editor","* FIXED: File is not published from tmp to media\/files if you save the block.","## Raw Editor","* DONE ready","## Medialib","* DONE","## Posts","* Setup","## Plugins","* Asset Class","## Frontend","* DONE\n* DONE: Test restrictions","## ToDos","Biig blocks:","* DONE: Media Library\n* DONE: Posts\n* DONE: Setup\n* DONE: Recover Password","Small features:","* DONE: Merge processAssets modell\n* DONE: Table of content duplicated for published pages\n* DONE: Session handling: csrf fail and session start error if restrictions are active\n* DONE: Image and files for meta\n* Backend fields\n* Proxy\n* Editor: Warn if open another block\n* Image generation on the fly\n* Assets\n* Bug: Navigation frontend if unpublished pages\n* Sitemap and ping\n* Captcha\n* Clear Cache\n* Security Log\n* Customfields not styled yet.","Cleanups:","* Events\n* Error messages\n* Translations","## Select userroles","* Userroles for file restriction: in vue-blox-components loaded via api\n* Userroles for userfields: in php model user getUserFields()\n* Userroles for meta: in php controller apiAuthorMeta getMeta()\n* Plugins and themes: in php model extension getThemeDefinitions()","## License Check","* On activation in apiControllerExtension. It checks the license in yaml.\n* In plugin php code with setPremiumLicense\n* In static plugins, it checks manual premium list and method setPremiumLicense and more "]

File diff suppressed because one or more lines are too long

View File

@@ -38,7 +38,7 @@
navtitle: 'To Dos'
hide: false
noindex: false
path: /00-welcome/05-todos.md
path: /00-welcome/05-todos.txtmd
keyPath: '0.5'
/cyanine-theme:
navtitle: 'cyanine theme'

View File

@@ -192,7 +192,7 @@ class Assets
{
$this->JS[] = $axiosUrl;
$axios = '<script>const myaxios = axios.create({ baseURL: \'' . $this->baseUrl . '\' });</script>';
$axios = '<script>const tmaxios = axios.create({ baseURL: \'' . $this->baseUrl . '\' });</script>';
$this->JS[] = $axios;
}
}

View File

@@ -7,13 +7,6 @@ use Slim\Routing\RouteContext;
use Typemill\Models\StorageWrapper;
use Typemill\Events\OnTwigLoaded;
# use Psr\Container\ContainerInterface;
# use Typemill\Models\Folder;
# use Typemill\Models\WriteCache;
# use Typemill\Models\WriteYaml;
# use Typemill\Events\OnPageReady;
# use Typemill\Events\OnPagetreeLoaded;
abstract class Controller
{
# holds the container
@@ -114,7 +107,7 @@ abstract class Controller
# always add null as first option in selectboxes.
$options = [null => null];
if(is_array($field['options']))
if(isset($field['options']) && is_array($field['options']))
{
$options = array_merge($options, $field['options']);
}

View File

@@ -4,7 +4,7 @@ namespace Typemill\Controllers;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Typemill\Models\ProcessAssets;
use Typemill\Models\Media;
use Typemill\Models\StorageWrapper;
class ControllerApiFile extends Controller
@@ -204,7 +204,7 @@ class ControllerApiFile extends Controller
}
}
$fileProcessor = new ProcessAssets();
$media = new Media();
$fileinfo = $fileProcessor->storeFile($params['file'], $params['name']);
$filePath = str_replace('media/files', 'media/tmp', $fileinfo['url']);
@@ -221,7 +221,7 @@ class ControllerApiFile extends Controller
if(!$mtype OR !$this->checkAllowedMimeTypes($mtype, $extension))
{
$fileProcessor->clearTempFolder();
$media->clearTempFolder();
$response->getBody()->write(json_encode([
'message' => 'The mime-type is missing, not allowed or does not fit to the file extension.'
@@ -231,14 +231,6 @@ class ControllerApiFile extends Controller
}
}
/*
# publish file directly, used for example by file field for meta-tabs
if(isset($params['publish']) && $params['publish'])
{
$fileProcessor->publishFile();
}
*/
$response->getBody()->write(json_encode([
'message' => 'File has been stored',
'fileinfo' => $fileinfo,

View File

@@ -4,7 +4,7 @@ namespace Typemill\Controllers;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Typemill\Models\ProcessAssets;
use Typemill\Models\Media;
use Typemill\Models\StorageWrapper;
use Typemill\Extensions\ParsedownExtension;
@@ -135,19 +135,19 @@ class ControllerApiImage extends Controller
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
}
$img = new ProcessAssets();
$media = new Media();
if($this->settingActive('allowsvg'))
{
$img->addAllowedExtension('svg');
$media->addAllowedExtension('svg');
}
# prepare the image
if(!$img->prepareImage($params['image'], $params['name']))
if(!$media->prepareImage($params['image'], $params['name']))
{
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
'message' => $media->errors[0],
'fullerrors' => $media->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
@@ -156,35 +156,35 @@ class ControllerApiImage extends Controller
# check if image name already exisits in live folder and create an unique name (do not overwrite existing files)
$storage = new StorageWrapper('\Typemill\Models\Storage');
$uniqueImageName = $storage->createUniqueImageName($img->getFilename(), $img->getExtension());
$img->setFilename($uniqueImageName);
$media->setFilename($uniqueImageName);
# store the original image
if(!$img->storeOriginalToTmp())
if(!$media->storeOriginalToTmp())
{
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
'message' => $media->errors[0],
'fullerrors' => $media->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
}
# if image is not resizable (animated gif or svg)
if(!$img->isResizable())
if(!$media->isResizable())
{
if($img->saveOriginalForAll())
if($media->saveOriginalForAll())
{
$response->getBody()->write(json_encode([
'message' => 'Image saved successfully',
'name' => 'media/live/' . $img->getFullName(),
'name' => 'media/live/' . $media->getFullName(),
]));
return $response->withHeader('Content-Type', 'application/json');
}
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
'message' => $media->errors[0],
'fullerrors' => $media->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
@@ -193,36 +193,23 @@ class ControllerApiImage extends Controller
# for all other image types, check if they should be transformed to webp
if($this->settingActive('convertwebp'))
{
$img->setExtension('webp');
$media->setExtension('webp');
}
if(!$img->storeRenditionsToTmp($this->settings['images']))
if(!$media->storeRenditionsToTmp($this->settings['images']))
{
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
'message' => $media->errors[0],
'fullerrors' => $media->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
}
/*
if(isset($params['publish']) && $params['publish'])
{
if(!$img->publishImage($img->getFullName()))
{
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
}
}
*/
$response->getBody()->write(json_encode([
'message' => 'Image saved successfully',
'name' => 'media/tmp/' . $img->getFullName(),
'name' => 'media/tmp/' . $media->getFullName(),
]));
return $response->withHeader('Content-Type', 'application/json');
@@ -317,14 +304,14 @@ class ControllerApiImage extends Controller
$imageData64 = 'data:image/jpeg;base64,' . base64_encode($imageData);
$img = new ProcessAssets();
$media = new Media();
# prepare the image
if(!$img->prepareImage($imageData64, $class . '-' . $videoID . '.jpg'))
if(!$media->prepareImage($imageData64, $class . '-' . $videoID . '.jpg'))
{
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
'message' => $media->errors[0],
'fullerrors' => $media->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
@@ -332,15 +319,15 @@ class ControllerApiImage extends Controller
# check if image name already exisits in live folder and create an unique name (do not overwrite existing files)
$storage = new StorageWrapper('\Typemill\Models\Storage');
$uniqueImageName = $storage->createUniqueImageName($img->getFilename(), $img->getExtension());
$img->setFilename($uniqueImageName);
$uniqueImageName = $storage->createUniqueImageName($media->getFilename(), $media->getExtension());
$media->setFilename($uniqueImageName);
# store the original image
if(!$img->storeOriginalToTmp())
if(!$media->storeOriginalToTmp())
{
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
'message' => $media->errors[0],
'fullerrors' => $media->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
@@ -349,25 +336,25 @@ class ControllerApiImage extends Controller
# for all other image types, check if they should be transformed to webp
if($this->settingActive('convertwebp'))
{
$img->setExtension('webp');
$media->setExtension('webp');
}
# set to youtube size
$sizes = $this->settings['images'];
$sizes['live'] = ['width' => 560, 'height' => 315];
if(!$img->storeRenditionsToTmp($sizes))
if(!$media->storeRenditionsToTmp($sizes))
{
$response->getBody()->write(json_encode([
'message' => $img->errors[0],
'fullerrors' => $img->errors,
'message' => $media->errors[0],
'fullerrors' => $media->errors,
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
}
# now publish directly
$livePath = $storage->publishImage($img->getFullName());
$livePath = $storage->publishImage($media->getFullName());
if($livePath)
{

View File

@@ -70,8 +70,8 @@ class ControllerApiSystemExtensions extends Controller
$objectdata = [];
if($params['type'] == 'plugins')
{
$objectdata[$params['type']][$params['name']] = $this->settings[$params['type']][$params['name']];
$objectdata[$params['type']][$params['name']]['active'] = $params['checked'];
$objectdata['plugins'][$params['name']] = $this->settings[$params['type']][$params['name']];
$objectdata['plugins'][$params['name']]['active'] = $params['checked'];
}
elseif($params['type'] == 'themes')
{

View File

@@ -18,11 +18,12 @@ class ControllerApiSystemPlugins extends Controller
$extension = new Extension();
$formdefinitions = $extension->getPluginDefinition($pluginname);
$formdefinitions = $this->addDatasets($formdefinitions['forms']['fields']);
$plugindata = [];
# validate input
$validator = new Validation();
$validatedOutput = $this->recursiveValidation($validator, $formdefinitions['forms']['fields'], $plugininput);
$validatedOutput = $this->recursiveValidation($validator, $formdefinitions, $plugininput);
if(!empty($this->errors))
{
$response->getBody()->write(json_encode([

View File

@@ -18,11 +18,12 @@ class ControllerApiSystemThemes extends Controller
$extension = new Extension();
$formdefinitions = $extension->getThemeDefinition($themename);
$formdefinitions = $this->addDatasets($formdefinitions['forms']['fields']);
$themedata = [];
# validate input
$validator = new Validation();
$validatedOutput = $this->recursiveValidation($validator, $formdefinitions['forms']['fields'], $themeinput);
$validatedOutput = $this->recursiveValidation($validator, $formdefinitions, $themeinput);
if(!empty($this->errors))
{
$response->getBody()->write(json_encode([

View File

@@ -17,6 +17,7 @@ use Typemill\Events\OnMarkdownLoaded;
use Typemill\Events\OnContentArrayLoaded;
use Typemill\Events\OnHtmlLoaded;
use Typemill\Events\OnRestrictionsLoaded;
use Typemill\Events\OnPageReady;
class ControllerWebFrontend extends Controller
@@ -231,10 +232,7 @@ class ControllerWebFrontend extends Controller
$assets->addMeta('twitter_card','<meta name="twitter:card" content="summary_large_image">');
}
$route = empty($args) && isset($this->settings['themes'][$theme]['cover']) ? 'cover.twig' : 'index.twig';
return $this->c->get('view')->render($response, $route, [
$pagedata = [
'home' => false,
'navigation' => $liveNavigation,
'title' => $title,
@@ -247,7 +245,15 @@ class ControllerWebFrontend extends Controller
'logo' => $logo,
'favicon' => $favicon,
'currentpage' => $currentpage
]);
];
$morepagedata = $this->c->get('dispatcher')->dispatch(new OnPageReady([]), 'onPageReady')->getData();
$pagedata = array_merge($pagedata, $morepagedata);
$route = empty($args) && isset($this->settings['themes'][$theme]['cover']) ? 'cover.twig' : 'index.twig';
return $this->c->get('view')->render($response, $route, $pagedata);
}

View File

@@ -23,7 +23,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher')
);
$settingsModel = new Settings();
@@ -61,7 +62,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher')
);
$extension = new Extension();
@@ -112,7 +114,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher'),
);
$extension = new Extension();
@@ -162,7 +165,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher'),
);
$license = new License();
@@ -201,7 +205,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher'),
);
$username = $request->getAttribute('c_username');
@@ -238,7 +243,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher'),
);
$user = new User();
@@ -281,7 +287,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher'),
);
$user = new User();
@@ -322,7 +329,8 @@ class ControllerWebSystem extends Controller
$systemNavigation = $navigation->getSystemNavigation(
$userrole = $request->getAttribute('c_userrole'),
$acl = $this->c->get('acl'),
$urlinfo = $this->c->get('urlinfo')
$urlinfo = $this->c->get('urlinfo'),
$dispatcher = $this->c->get('dispatcher'),
);
return $this->c->get('view')->render($response, 'system/usernew.twig', [

View File

@@ -1,593 +0,0 @@
<?php
class oldclasses
{
protected $errors = [];
########### CHECK IF NEEDED IN CONTROLLER
protected function setUrlCollection($uri)
{
$scheme = $uri->getScheme();
$authority = $uri->getAuthority();
$protocol = ($scheme ? $scheme . ':' : '') . ($authority ? '//' . $authority : '');
$this->basePath = $this->c->get('basePath');
$this->currentPath = $uri->getPath();
$this->fullBaseUrl = $protocol . $this->basePath;
$this->fullCurrentUrl = $protocol . $this->currentPath;
$this->urlCollection = [
'basePath' => $this->basePath,
'currentPath' => $this->currentPath,
'fullBaseUrl' => $this->fullBaseUrl,
'fullCurrentUrl' => $this->fullCurrentUrl
];
}
# render page for frontend
protected function render($response, $route, $data)
{
# why commented this out??
$data = $this->c->dispatcher->dispatch('onPageReady', new OnPageReady($data))->getData();
if(isset($_SESSION['old']))
{
unset($_SESSION['old']);
}
$response = $response->withoutHeader('Server');
$response = $response->withAddedHeader('X-Powered-By', 'Typemill');
if(!isset($this->settings['headersoff']) or !$this->settings['headersoff'])
{
$response = $response->withAddedHeader('X-Content-Type-Options', 'nosniff');
$response = $response->withAddedHeader('X-Frame-Options', 'SAMEORIGIN');
$response = $response->withAddedHeader('X-XSS-Protection', '1;mode=block');
$response = $response->withAddedHeader('Referrer-Policy', 'no-referrer-when-downgrade');
if($this->c->request->getUri()->getScheme() == 'https')
{
$response = $response->withAddedHeader('Strict-Transport-Security', 'max-age=63072000');
}
}
return $this->c->view->render($response, $route, $data);
}
# render 404 for frontend
protected function render404($response, $data = NULL)
{
return $this->c->view->render($response->withStatus(404), '/404.twig', $data);
}
# render page for authors (admin-area)
protected function renderIntern($response, $route, $data)
{
if(isset($_SESSION['old']))
{
unset($_SESSION['old']);
}
$response = $response->withoutHeader('Server');
$response = $response->withAddedHeader('X-Powered-By', 'Typemill');
if(!isset($this->settings['headersoff']) or !$this->settings['headersoff'])
{
$response = $response->withAddedHeader('X-Content-Type-Options', 'nosniff');
$response = $response->withAddedHeader('X-Frame-Options', 'SAMEORIGIN');
$response = $response->withAddedHeader('X-XSS-Protection', '1;mode=block');
$response = $response->withAddedHeader('Referrer-Policy', 'no-referrer-when-downgrade');
if($this->c->request->getUri()->getScheme() == 'https')
{
$response = $response->withAddedHeader('Strict-Transport-Security', 'max-age=63072000');
}
}
return $this->c->view->render($response, $route, $data);
}
# render 404 for authors
protected function renderIntern404($response, $data = NULL)
{
return $this->c->view->render($response->withStatus(404), '/intern404.twig', $data);
}
########### MOVE TO GLOBAL API ??
public function clearCache($request, $response, $args)
{
$this->uri = $request->getUri()->withUserInfo('');
$dir = $this->settings['basePath'] . 'cache';
$error = $this->writeCache->deleteCacheFiles($dir);
if($error)
{
return $response->withJson(['errors' => $error], 500);
}
# create a new draft structure
$this->setFreshStructureDraft();
# create a new draft structure
$this->setFreshStructureLive();
# create a new draft structure
$this->setFreshNavigation();
# update the sitemap
$this->updateSitemap();
return $response->withJson(array('errors' => false));
}
############ CHECK IF NEEDED FOR API IMAGE ???
protected function saveImages($imageFields, $userInput, $userSettings, $files)
{
# initiate image processor with standard image sizes
$processImages = new ProcessImage($userSettings['images']);
if(!$processImages->checkFolders('images'))
{
$this->c->flash->addMessage('error', 'Please make sure that your media folder exists and is writable.');
return false;
}
foreach($imageFields as $fieldName => $imageField)
{
if(isset($userInput[$fieldName]))
{
# handle single input with single file upload
$image = $files[$fieldName];
if($image->getError() === UPLOAD_ERR_OK)
{
# not the most elegant, but createImage expects a base64-encoded string.
$imageContent = $image->getStream()->getContents();
$imageData = base64_encode($imageContent);
$imageSrc = 'data: ' . $image->getClientMediaType() . ';base64,' . $imageData;
if($processImages->createImage($imageSrc, $image->getClientFilename(), $userSettings['images'], $overwrite = NULL))
{
# returns image path to media library
$userInput[$fieldName] = $processImages->publishImage();
}
}
}
}
return $userInput;
}
############ NAVIGATION ???
# reads the cached structure with published and non-published pages for the author
# setStructureDraft
protected function getStructureForAuthors($userrole, $username)
{
# get the cached structure
$this->structureDraft = $this->writeCache->getCache('cache', $this->structureDraftName);
# if there is no cached structure
if(!$this->structureDraft)
{
return $this->setFreshStructureDraft();
}
return true;
}
# creates a fresh structure with published and non-published pages for the author
# setFreshStrutureDraft
protected function createNewStructureForAuthors()
{
# scan the content of the folder
$pagetreeDraft = Folder::scanFolder($this->settings['rootPath'] . $this->settings['contentFolder'], $draft = true );
# if there is content, then get the content details
if(count($pagetreeDraft) > 0)
{
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $this->getExtended();
# create an array of object with the whole content of the folder and changes from extended file
$this->structureDraft = Folder::getFolderContentDetails($pagetreeDraft, $extended, $this->settings, $this->uri->getBaseUrl(), $this->uri->getBasePath());
# cache structure draft
$this->writeCache->updateCache('cache', $this->structureDraftName, 'lastCache.txt', $this->structureDraft);
return true;
}
return false;
}
# reads the cached structure of published pages
# setStrutureLive
protected function getStructureForReaders()
{
# get the cached structure
$this->structureLive = $this->writeCache->getCache('cache', $this->structureLiveName);
# if there is no cached structure
if(!$this->structureLive)
{
return $this->setFreshStructureLive();
}
return true;
}
# creates a fresh structure with published pages
protected function setFreshStructureLive()
{
# scan the content of the folder
$pagetreeLive = Folder::scanFolder($this->settings['rootPath'] . $this->settings['contentFolder'], $draft = false );
# if there is content, then get the content details
if($pagetreeLive && count($pagetreeLive) > 0)
{
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $this->getExtended();
# create an array of object with the whole content of the folder and changes from extended file
$this->structureLive = Folder::getFolderContentDetails($pagetreeLive, $extended, $this->settings, $this->uri->getBaseUrl(), $this->uri->getBasePath());
# cache structure live
$this->writeCache->updateCache('cache', $this->structureLiveName, 'lastCache.txt', $this->structureLive);
return true;
}
return false;
}
# reads the live navigation from cache (live structure without hidden pages)
protected function setNavigation()
{
# get the cached structure
$this->navigation = $this->writeCache->getCache('cache', 'navigation.txt');
# if there is no cached structure
if(!$this->navigation)
{
return $this->setFreshNavigation();
}
return true;
}
# creates a fresh live navigation (live structure without hidden pages)
protected function setFreshNavigation()
{
if(!$this->extended)
{
$extended = $this->getExtended();
}
if($this->containsHiddenPages($this->extended))
{
if(!$this->structureLive)
{
$this->setStructureLive();
}
$structureLive = $this->c->dispatcher->dispatch('onPagetreeLoaded', new OnPagetreeLoaded($this->structureLive))->getData();
$this->navigation = $this->createNavigation($structureLive);
# cache navigation
$this->writeCache->updateCache('cache', 'navigation.txt', false, $this->navigation);
return true;
}
# make sure no old navigation file is left
$this->writeCache->deleteFileWithPath('cache' . DIRECTORY_SEPARATOR . 'navigation.txt');
return false;
}
# create navigation from structure
protected function createNavigation($structureLive)
{
foreach ($structureLive as $key => $element)
{
if($element->hide === true)
{
unset($structureLive[$key]);
}
elseif(isset($element->folderContent))
{
$structureLive[$key]->folderContent = $this->createNavigation($element->folderContent);
}
}
return $structureLive;
}
# reads the cached structure with published and non-published pages for the author
protected function setStructureDraft()
{
# get the cached structure
$this->structureDraft = $this->writeCache->getCache('cache', $this->structureDraftName);
# if there is no cached structure
if(!$this->structureDraft)
{
return $this->setFreshStructureDraft();
}
return true;
}
# creates a fresh structure with published and non-published pages for the author
protected function setFreshStructureDraft()
{
# scan the content of the folder
$pagetreeDraft = Folder::scanFolder($this->settings['rootPath'] . $this->settings['contentFolder'], $draft = true );
# if there is content, then get the content details
if(count($pagetreeDraft) > 0)
{
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $this->getExtended();
# create an array of object with the whole content of the folder and changes from extended file
$this->structureDraft = Folder::getFolderContentDetails($pagetreeDraft, $extended, $this->settings, $this->uri->getBaseUrl(), $this->uri->getBasePath());
# cache structure draft
$this->writeCache->updateCache('cache', $this->structureDraftName, 'lastCache.txt', $this->structureDraft);
return true;
}
return false;
}
# reads the cached structure of published pages
protected function setStructureLive()
{
# get the cached structure
$this->structureLive = $this->writeCache->getCache('cache', $this->structureLiveName);
# if there is no cached structure
if(!$this->structureLive)
{
return $this->setFreshStructureLive();
}
return true;
}
# creates a fresh structure with published pages
protected function setFreshStructureLive()
{
# scan the content of the folder
$pagetreeLive = Folder::scanFolder($this->settings['rootPath'] . $this->settings['contentFolder'], $draft = false );
# if there is content, then get the content details
if($pagetreeLive && count($pagetreeLive) > 0)
{
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $this->getExtended();
# create an array of object with the whole content of the folder and changes from extended file
$this->structureLive = Folder::getFolderContentDetails($pagetreeLive, $extended, $this->settings, $this->uri->getBaseUrl(), $this->uri->getBasePath());
# cache structure live
$this->writeCache->updateCache('cache', $this->structureLiveName, 'lastCache.txt', $this->structureLive);
return true;
}
return false;
}
# reads the live navigation from cache (live structure without hidden pages)
protected function setNavigation()
{
# get the cached structure
$this->navigation = $this->writeCache->getCache('cache', 'navigation.txt');
# if there is no cached structure
if(!$this->navigation)
{
return $this->setFreshNavigation();
}
return true;
}
# creates a fresh live navigation (live structure without hidden pages)
protected function setFreshNavigation()
{
if(!$this->extended)
{
$extended = $this->getExtended();
}
if($this->containsHiddenPages($this->extended))
{
if(!$this->structureLive)
{
$this->setStructureLive();
}
$structureLive = $this->c->dispatcher->dispatch('onPagetreeLoaded', new OnPagetreeLoaded($this->structureLive))->getData();
$this->navigation = $this->createNavigation($structureLive);
# cache navigation
$this->writeCache->updateCache('cache', 'navigation.txt', false, $this->navigation);
return true;
}
# make sure no old navigation file is left
$this->writeCache->deleteFileWithPath('cache' . DIRECTORY_SEPARATOR . 'navigation.txt');
return false;
}
# create navigation from structure
protected function createNavigation($structureLive)
{
foreach ($structureLive as $key => $element)
{
if($element->hide === true)
{
unset($structureLive[$key]);
}
elseif(isset($element->folderContent))
{
$structureLive[$key]->folderContent = $this->createNavigation($element->folderContent);
}
}
return $structureLive;
}
protected function getExtended()
{
$yaml = new writeYaml();
if(!$this->extended)
{
$this->extended = $yaml->getYaml('cache', 'structure-extended.yaml');
}
if(!$this->extended)
{
# scan the content of the folder
$pagetreeDraft = Folder::scanFolder($this->settings['rootPath'] . $this->settings['contentFolder'], $draft = true );
# if there is content, then get the content details
if(count($pagetreeDraft) == 0)
{
return false;
}
# create an array of object with the whole content of the folder and changes from extended file
$structureDraft = Folder::getFolderContentDetails($pagetreeDraft, $extended = false, $this->settings, $this->uri->getBaseUrl(), $this->uri->getBasePath());
$this->extended = $this->createExtended($this->settings['rootPath'] . $this->settings['contentFolder'], $yaml, $structureDraft);
$yaml->updateYaml('cache', 'structure-extended.yaml', $this->extended);
}
return $this->extended;
}
# creates a file that holds all hide flags and navigation titles
# reads all meta-files and creates an array with url => ['hide' => bool, 'navtitle' => 'bla']
public function createExtended($contentPath, $yaml, $structureLive, $extended = NULL)
{
if(!$extended)
{
$extended = [];
}
foreach ($structureLive as $key => $item)
{
# $filename = ($item->elementType == 'folder') ? DIRECTORY_SEPARATOR . 'index.yaml' : $item->pathWithoutType . '.yaml';
$filename = $item->pathWithoutType . '.yaml';
if(file_exists($contentPath . $filename))
{
# read file
$meta = $yaml->getYaml('content', $filename);
$extended[$item->urlRelWoF]['hide'] = isset($meta['meta']['hide']) ? $meta['meta']['hide'] : false;
$extended[$item->urlRelWoF]['navtitle'] = isset($meta['meta']['navtitle']) ? $meta['meta']['navtitle'] : '';
}
if ($item->elementType == 'folder')
{
$extended = $this->createExtended($contentPath, $yaml, $item->folderContent, $extended);
}
}
return $extended;
}
# only backoffice
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;
}
# only backoffice
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);
}
}
}
# checks if there is a hidden page, returns true on first find
protected function containsHiddenPages($extended)
{
foreach($extended as $element)
{
if(isset($element['hide']) && $element['hide'] === true)
{
return true;
}
}
return false;
}
}

View File

@@ -18,6 +18,8 @@ class ParsedownExtension extends \ParsedownExtra
# show anchor next to headline?
$this->showAnchor = isset($settings['headlineanchors']) ? $settings['headlineanchors'] : false;
$this->headlines = [];
# extend link schemes
$urlschemes = ( isset($settings['urlschemes']) && !empty($settings['urlschemes']) ) ? explode(",", $settings['urlschemes']) : false;
if($urlschemes)
@@ -345,7 +347,7 @@ class ParsedownExtension extends \ParsedownExtra
# Headlines
public $headlines = array();
public $headlines = [];
protected function blockHeader($Line)
{
@@ -372,6 +374,7 @@ class ParsedownExtension extends \ParsedownExtra
if($this->showAnchor && $level > 1)
{
# should we add more info like level so duplicate headline text is possible?
$text = "[#](#h-$headline){.tm-heading-anchor}" . $text;
}
@@ -389,7 +392,11 @@ class ParsedownExtension extends \ParsedownExtra
)
);
$this->headlines[] = array('level' => $level, 'name' => $Block['element']['name'], 'attribute' => $Block['element']['attributes']['id'], 'text' => $tocText);
# fix: make sure no duplicates in headlines if user logged in and restrictions on
if(!isset($this->headlines[$headline]))
{
$this->headlines[$headline] = array('level' => $level, 'name' => $Block['element']['name'], 'attribute' => $Block['element']['attributes']['id'], 'text' => $tocText);
}
return $Block;
}
@@ -406,11 +413,15 @@ class ParsedownExtension extends \ParsedownExtra
}
# build the markup for table of contents
# build the markup for table of contents
public function buildTOC($headlines)
{
$markup = '<ul class="TOC">';
# we have to reindex the array
$headlines = array_values($headlines);
foreach($headlines as $key => $headline)
{
$thisLevel = $headline['level'];
@@ -421,9 +432,9 @@ class ParsedownExtension extends \ParsedownExtra
{
$markup .= '<ul>';
}
$markup .= '<li class="' . $headline['name'] . '"><a href="#' . $headline['attribute'] . '">' . $headline['text'] . '</a>';
if($thisLevel == $nextLevel )
{
$markup .= '</li>';

View File

@@ -10,7 +10,7 @@ use Typemill\Models\User;
use Typemill\Static\Session;
class ApiAuthentication
{
{
public function __invoke(Request $request, RequestHandler $handler)
{
$routeContext = RouteContext::fromRequest($request);

View File

@@ -5,7 +5,6 @@ namespace Typemill\Middleware;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Flash\Messages;
# use Slim\Views\Twig;
class FlashMessages
{

View File

@@ -205,7 +205,7 @@ class Content
}
public function markdownArrayToText(array $markdownArray)
{
{
return $this->parsedown->arrayBlocksToMarkdown($markdownArray);
}

View File

@@ -5,7 +5,7 @@ namespace Typemill\Models;
use Typemill\Models\Folder;
use Typemill\Static\Slug;
class ProcessAssets
class Media
{
public $errors = [];

View File

@@ -4,6 +4,7 @@ namespace Typemill\Models;
use Typemill\Models\StorageWrapper;
use Typemill\Models\Folder;
use Typemill\Events\OnSystemnaviLoaded;
class Navigation extends Folder
{
@@ -109,10 +110,10 @@ class Navigation extends Folder
return $allowedmainnavi;
}
public function getSystemNavigation($userrole, $acl, $urlinfo)
public function getSystemNavigation($userrole, $acl, $urlinfo, $dispatcher)
{
$systemnavi = $this->storage->getYaml('systemSettings', '', 'systemnavi.yaml');
# $systemnavi = $this->c->get('dispatcher')->dispatch(new OnSystemnaviLoaded($systemnavi), 'onSystemnaviLoaded')->getData();
$systemnavi = $dispatcher->dispatch(new OnSystemnaviLoaded($systemnavi), 'onSystemnaviLoaded')->getData();
$allowedsystemnavi = [];

View File

@@ -129,6 +129,16 @@ class Settings
# merge usersettings with new settings
$settings = array_merge($userSettings, $newSettings);
# make sure that multidimensional arrays are merged correctly
# for example: only one plugin data will be passed with new settings, with array merge all others will be deleted.
foreach($newSettings as $key => $settingsItem)
{
if(is_array($settingsItem) && isset($userSettings[$key]))
{
$settings[$key] = array_merge($userSettings[$key], $newSettings[$key]);
}
}
if($this->storage->updateYaml('settingsFolder', '', 'settings.yaml', $settings))
{
return true;

View File

@@ -782,355 +782,4 @@ class Storage
return $result;
}
/*
public function getFileDetailsBREAK($name)
{
$name = basename($name);
if (!in_array($name, array(".","..")) && file_exists($this->fileFolder . $name))
{
$filedetails = [
'name' => $name,
'timestamp' => filemtime($this->fileFolder . $name),
'bytes' => filesize($this->fileFolder . $name),
'info' => pathinfo($this->fileFolder . $name),
'url' => 'media/files/' . $name,
];
return $filedetails;
}
return false;
}
public function getStorageInfoBREAK($item)
{
if(isset($this->$item))
{
return $this->$item;
}
return false;
}
public function checkFolderBREAK($folder)
{
$folderpath = $this->basepath . $folder;
if(!is_dir($folderpath) OR !is_writable($folderpath))
{
$this->error = "The folder $folder does not exist or is not writable.";
return false;
}
return true;
}
public function createFolderBREAK($folder)
{
$folderpath = $this->basepath . $folder;
if(is_dir($folderpath))
{
return true;
}
if(!mkdir($folderpath, 0755, true))
{
$this->error = "Could not create folder $folder.";
return false;
}
return true;
}
public function checkFileBREAK($folder, $filename)
{
if(!file_exists($this->basepath . $folder . DIRECTORY_SEPARATOR . $filename))
{
$this->error = "The file $filename in folder $folder does not exist.";
return false;
}
return true;
}
public function writeFileBREAK($folder, $filename, $data, $method = NULL)
{
echo '<pre>';
var_dump($folder);
die();
if(!$this->checkFolder($folder))
{
if(!$this->createFolder($folder))
{
return false;
}
}
$filepath = $this->basepath . $folder . DIRECTORY_SEPARATOR . $filename;
$openfile = @fopen($filepath, "w");
if(!$openfile)
{
$this->error = "Could not open and read the file $filename in folder $folder.";
return false;
}
# serialize, json_decode
if($method && is_callable($method))
{
$data = $method($data);
}
$writefile = fwrite($openfile, $data);
if(!$writefile)
{
$this->error = "Could not write to the file $filename in folder $folder.";
return false;
}
fclose($openfile);
return true;
}
public function getFileBREAK($folder, $filename, $method = NULL)
{
if($this->checkFile($folder, $filename))
{
# ??? should be with basepath???
$fileContent = file_get_contents($folder . DIRECTORY_SEPARATOR . $filename);
# use unserialise or json_decode
if($method && is_callable($method))
{
$fileContent = $method($fileContent);
}
return $fileContent;
}
return false;
}
public function renameFileBREAK($folder, $oldname, $newname)
{
$oldFilePath = $this->basepath . $folder . DIRECTORY_SEPARATOR . $oldname;
$newFilePath = $this->basepath . $folder . DIRECTORY_SEPARATOR . $newname;
if(!file_exists($oldFilePath))
{
return false;
}
if(!rename($oldFilePath, $newFilePath))
{
return false;
}
return true;
}
public function deleteFileBREAK($folder, $filename)
{
if($this->checkFile($folder, $filename))
{
if(unlink($this->basepath . $folder . DIRECTORY_SEPARATOR . $filename))
{
return true;
}
$this->error = "We found the file but could not delete $filename";
}
return false;
}
# used to sort the navigation / files
public function moveContentFileBREAK($item, $folderPath, $index, $date = null)
{
$filetypes = array('md', 'txt', 'yaml');
# set new order as string
$newOrder = ($index < 10) ? '0' . $index : $index;
$newPath = $this->contentFolder . $folderPath . DIRECTORY_SEPARATOR . $newOrder . '-' . $item->slug;
if($item->elementType == 'folder')
{
$oldPath = $this->contentFolder . $item->path;
if(@rename($oldPath, $newPath))
{
return true;
}
return false;
}
# create old path but without filetype
$oldPath = substr($item->path, 0, strpos($item->path, "."));
$oldPath = $this->contentFolder . $oldPath;
$result = true;
foreach($filetypes as $filetype)
{
$oldFilePath = $oldPath . '.' . $filetype;
$newFilePath = $newPath . '.' . $filetype;
#check if file with filetype exists and rename
if($oldFilePath != $newFilePath && file_exists($oldFilePath))
{
if(@rename($oldFilePath, $newFilePath))
{
$result = $result;
}
else
{
$result = false;
}
}
}
return $result;
}
public function checkPath($folder)
{
$folderPath = $this->basepath . $folder;
if(!is_dir($folderPath))
{
if(@mkdir($folderPath, 0774, true))
{
return true;
}
else
{
throw new \Exception("The folder '{$folderPath}' is missing and we could not create it. Please create the folder manually on your server.");
# return false;
}
}
if(@is_writable($folderPath))
{
return true;
}
else
{
throw new \Exception("Please make the folder '{$folderPath}' writable.");
# return false;
}
return true;
}
/*
public function checkFile($folder, $file)
{
if(!file_exists($this->basePath . $folder . DIRECTORY_SEPARATOR . $file))
{
return false;
}
return true;
}
public function checkFileWithPath($filepath)
{
if(!file_exists($this->basePath . $filepath))
{
return false;
}
return true;
}
public function writeFile($folder, $file, $data)
{
if($this->checkPath($folder))
{
$filePath = $this->basePath . $folder . DIRECTORY_SEPARATOR . $file;
$openFile = @fopen($filePath, "w");
if(!$openFile)
{
return false;
}
fwrite($openFile, $data);
fclose($openFile);
return true;
}
return false;
}
public function getFile($folderName, $fileName)
{
if($this->checkFile($folderName, $fileName))
{
$fileContent = file_get_contents($folderName . DIRECTORY_SEPARATOR . $fileName);
return $fileContent;
}
return false;
}
public function getFileWithPath($filepath)
{
if($this->checkFileWithPath($filepath))
{
$fileContent = file_get_contents($filepath);
return $fileContent;
}
return false;
}
public function deleteFileWithPath($filepath)
{
if($this->checkFileWithPath($filepath))
{
unlink($this->basePath . $filepath);
return true;
}
return false;
}
public function renameFile($folder, $oldname, $newname)
{
$oldFilePath = $this->basePath . $folder . DIRECTORY_SEPARATOR . $oldname;
$newFilePath = $this->basePath . $folder . DIRECTORY_SEPARATOR . $newname;
if(!file_exists($oldFilePath))
{
return false;
}
if(@rename($oldFilePath, $newFilePath))
{
return true;
}
return false;
}
*/
}

View File

@@ -1,69 +0,0 @@
<?php
namespace Typemill\Models;
class ProcessFile extends ProcessAssets
{
public function storeFile($file, $name)
{
die('use processAssets instead of processFile');
$this->clearTempFolder();
$this->setPathInfo($name);
$this->decode($file);
$fullpath = $this->getFullPath();
if($this->filedata !== false && file_put_contents($fullpath, $this->filedata))
{
$size = filesize($this->getFullPath());
$size = $this->formatSizeUnits($size);
$title = str_replace('-', ' ', $this->filename);
$title = $title . ' (' . strtoupper($this->extension) . ', ' . $size .')';
return [
'title' => $title,
'name' => $this->filename,
'extension' => $this->extension,
'size' => $size,
'url' => 'media/files/' . $this->getFullName()
];
}
return false;
}
/**
* Moves the uploaded file to the upload directory. Only used for settings / NON VUE.JS uploads
*
* @param string $directory directory to which the file is moved
* @param UploadedFile $uploadedFile file uploaded file to move
* @return string filename of moved file
*/
public function moveUploadedFile(UploadedFile $uploadedFile, $overwrite = false, $name = false, $folder = NULL)
{
die('use processAssets instead of processFile');
$this->setFileName($uploadedFile->getClientFilename(), 'file');
if($name)
{
$this->setFileName($name . '.' . $this->extension, 'file', $overwrite);
}
$uploadedFile->moveTo($this->fileFolder . $this->getFullName());
return $this->getFullName();
}
}

View File

@@ -1,442 +0,0 @@
<?php
namespace Typemill\Models;
#use Slim\Http\UploadedFile;
use Typemill\Static\Slug;
class ProcessImage extends ProcessAssets
{
protected $allowedExtensions = ['png' => true, 'jpg' => true, 'jpeg' => true, 'webp' => true];
protected $animated = false;
protected $resizable = true;
protected $sizes = [];
public function prepareImage($image, $name)
{
die('use processAssets instead of processImages');
# change clear tmp folder and delete only old ones
$this->clearTempFolder();
#$this->checkFolders('image');
$this->decode($image);
$this->setPathInfo($name);
$this->checkAllowedExtension();
if(empty($this->errors))
{
return true;
}
return false;
}
public function storeOriginalToTmp()
{
die('use processAssets instead of processImages');
# $this->saveName();
$this->saveOriginal();
if(empty($this->errors))
{
return true;
}
return false;
}
public function storeRenditionsToTmp($sizes)
{
die('use processAssets instead of processImages');
# transform image-stream into image
$image = $this->createImage();
$originalsize = $this->getImageSize($image);
foreach($sizes as $destinationfolder => $desiredsize)
{
$desiredsize = $this->calculateSize($originalsize, $desiredsize);
$resizedImage = $this->resizeImage($image, $desiredsize, $originalsize);
$this->saveResizedImage($resizedImage, $destinationfolder, $this->extension);
imagedestroy($resizedImage);
}
imagedestroy($image);
if(empty($this->errors))
{
return true;
}
return false;
}
# add an allowed image extension like svg
public function addAllowedExtension(string $extension)
{
die('use processAssets instead of processImages');
$this->allowedExtensions[$extension] = true;
}
# force an image type like webp
public function setExtension(string $extension)
{
die('use processAssets instead of processImages');
$this->extension = $extension;
}
public function checkAllowedExtension()
{
die('use processAssets instead of processImages');
if(!isset($this->allowedExtensions[$this->extension]))
{
$this->errors[] = 'Images with this extension are not allowed.';
return false;
}
return true;
}
# check if image should not be resized (animated gif and svg)
public function isResizable()
{
die('use processAssets instead of processImages');
if($this->filetype == 'gif' && $this->detectAnimatedGif())
{
$this->resizable = false;
}
if($this->filetype == 'svg+xml')
{
$this->resizable = false;
}
return $this->resizable;
}
public function detectAnimatedGif()
{
die('use processAssets instead of processImages');
$is_animated = preg_match('#(\x00\x21\xF9\x04.{4}\x00\x2C.*){2,}#s', $this->filedata);
if ($is_animated == 1)
{
$this->animated = true;
}
return $this->animated;
}
# save the original image to temp folder
public function saveOriginal($destinationfolder = 'ORIGINAL')
{
die('use processAssets instead of processImages');
$path = $this->tmpFolder . $destinationfolder . '+' . $this->filename . '.' . $this->extension;
if(!file_put_contents($path, $this->filedata))
{
$this->errors[] = 'could not store the image in the temporary folder';
}
}
# save the original image for all sizes/folders
public function saveOriginalForAll()
{
die('use processAssets instead of processImages');
$this->saveOriginal('LIVE');
$this->saveOriginal('THUMBS');
}
public function createImage()
{
die('use processAssets instead of processImages');
return imagecreatefromstring($this->filedata);
}
public function getImageSize($image)
{
die('use processAssets instead of processImages');
return ['width' => imagesx($image), 'height' => imagesy($image)];
}
public function calculateSize(array $originalsize, array $desiredsize)
{
die('use processAssets instead of processImages');
# if desired size is bigger than the actual image, then drop the desired sizes and use the actual image size instead
if($desiredsize['width'] > $originalsize['width'])
{
return $originalsize;
}
if(!isset($desiredsize['height']))
{
$resizeFactor = $originalsize['width'] / $desiredsize['width'];
$desiredsize['height'] = round( ($originalsize['height'] / $resizeFactor), 0);
}
return $desiredsize;
}
public function resizeImage($image, array $desired, array $original)
{
die('use processAssets instead of processImages');
# resize
$ratio = max($desired['width']/$original['width'], $desired['height']/$original['height']);
$h = $desired['height'] / $ratio;
$x = ($original['width'] - $desired['width'] / $ratio) / 2;
$y = ($original['height'] - $desired['height'] / $ratio) / 2;
$w = $desired['width'] / $ratio;
$resizedImage = imagecreatetruecolor($desired['width'], $desired['height']);
# preserve transparency
if($this->extension == "gif" or $this->extension == "png" or $this->extension == "webp")
{
imagecolortransparent($resizedImage, imagecolorallocatealpha($resizedImage, 0, 0, 0, 127));
imagealphablending($resizedImage, false);
imagesavealpha($resizedImage, true);
}
imagecopyresampled($resizedImage, $image, 0, 0, $x, $y, $desired['width'], $desired['height'], $w, $h);
return $resizedImage;
}
public function saveResizedImage($resizedImage, string $destinationfolder, string $extension)
{
die('use processAssets instead of processImages');
$destinationfolder = strtoupper($destinationfolder);
switch($extension)
{
case "png":
$storedImage = imagepng( $resizedImage, $this->tmpFolder . $destinationfolder . '+' . $this->filename . '.png', 9 );
break;
case "gif":
$storedImage = imagegif( $resizedImage, $this->tmpFolder . $destinationfolder . '+' . $this->filename . '.gif' );
break;
case "webp":
$storedImage = imagewebp( $resizedImage, $this->tmpFolder . $destinationfolder . '+' . $this->filename . '.webp', 80);
break;
case "jpg":
case "jpeg":
$storedImage = imagejpeg( $resizedImage, $this->tmpFolder . $destinationfolder . '+' . $this->filename . '.' . $extension, 80);
break;
default:
$storedImage = false;
}
if(!$storedImage)
{
$failedImage = $this->tmpFolder . $destinationfolder . '+' . $this->filename . '.' . $extension;
$this->errors[] = "Could not store the resized version $failedImage";
return false;
}
return true;
}
# in use ??
public function deleteImageWithName($name)
{
die("processImage model deleteImageWithName please check method.");
# e.g. delete $name = 'logo...';
$name = basename($name);
if($name != '' && !in_array($name, array(".","..")))
{
foreach(glob($this->liveFolder . $name) as $file)
{
unlink($file);
}
foreach(glob($this->originalFolder . $name) as $file)
{
unlink($file);
}
foreach(glob($this->thumbFolder . $name) as $file)
{
unlink($file);
}
}
}
# in use ??
public function copyImage($name,$sourcefolder,$targetfolder)
{
die("processImage model copyImage please check method.");
copy($sourcefolder . $name, $targetfolder . $name);
}
/**
* Moves the uploaded file to the upload directory. Only used for settings / NON VUE.JS uploads
*
* @param string $directory directory to which the file is moved
* @param UploadedFile $uploadedFile file uploaded file to move
* @return string filename of moved file
*/
public function moveUploadedImage(UploadedFile $uploadedFile, $overwrite = false, $name = false, $folder = NULL)
{
die('use processAssets instead of processImages');
$this->setFileName($uploadedFile->getClientFilename(), 'file');
if($name)
{
$this->setFileName($name . '.' . $this->extension, 'file', $overwrite);
}
if(!$folder)
{
$folder = $this->liveFolder;
}
$uploadedFile->moveTo($folder . $this->getFullName());
return $this->getFullName();
}
/*
# save the image name as txt to temp folder
public function saveName()
{
$path = $this->tmpFolder . $this->filename . '.txt';
if(!fopen($path, "w"))
{
$this->errors[] = 'could not store the filename in the temporary folder';
}
}
*/
public function generateThumbs()
{
die('use processAssets instead of processImages');
# generate images from live folder to 'tmthumbs'
$liveImages = scandir($this->liveFolder);
$result = false;
foreach ($liveImages as $key => $name)
{
if (!in_array($name, array(".","..")))
{
$result = $this->generateThumbFromImageFile($name);
}
}
return $result;
}
public function generateThumbFromImageFile($filename)
{
die('use processAssets instead of processImages');
$this->setFileName($filename, 'image', $overwrite = true);
$image = $this->createImageFromPath($this->liveFolder . $filename, $this->extension);
$originalSize = $this->getImageSize($image);
$thumbSize = $this->desiredSizes['thumbs'];
$thumb = $this->imageResize($image, $originalSize, ['thumbs' => $thumbSize ], $this->extension);
$saveImage = $this->saveImage($this->thumbFolder, $thumb['thumbs'], $this->filename, $this->extension);
if($saveImage)
{
return true;
}
return false;
}
# filename and imagepath can be a tmp-version after upload.
public function generateSizesFromImageFile($filename, $imagePath)
{
die('use processAssets instead of processImages');
$this->setFileName($filename, 'image');
$image = $this->createImageFromPath($imagePath, $this->extension);
$originalSize = $this->getImageSize($image);
$resizedImages = $this->imageResize($image, $originalSize, $this->desiredSizes, $this->extension);
return $resizedImages;
}
public function grayscale($imagePath, $extension)
{
die('use processAssets instead of processImages');
$image = $this->createImageFromPath($imagePath, $extension);
imagefilter($image, IMG_FILTER_GRAYSCALE);
return $image;
}
public function createImageFromPath($imagePath, $extension)
{
die('use processAssets instead of processImages');
switch($extension)
{
case 'gif': $image = imagecreatefromgif($imagePath); break;
case 'jpg' :
case 'jpeg': $image = imagecreatefromjpeg($imagePath); break;
case 'png': $image = imagecreatefrompng($imagePath); break;
case 'webp': $image = imagecreatefromwebp($imagePath); break;
default: return 'image type not supported';
}
return $image;
}
}

View File

@@ -12,20 +12,29 @@ abstract class Plugin implements EventSubscriberInterface
{
protected $container;
protected $path;
protected $route;
protected $adminpath = false;
protected $adminroute = false;
protected $editorroute = false;
/**
* Constructor
*
*/
public function __construct($container)
{
$this->container = $container;
$this->urlinfo = $this->container->get('urlinfo');
$this->path = $this->urlinfo['currentpath'];
$this->route = $this->urlinfo['route'];
$this->route = ltrim($this->route, '/');
if(str_starts_with($this->route, 'tm/'))
{
$this->adminroute = true;
}
if(str_starts_with($this->route, 'tm/content/'))
{
$this->editorroute = true;
}
}
protected function getSettings()

View File

@@ -1,198 +0,0 @@
<?php
namespace Typemill\Static;
use Typemill\Models\StorageWrapper;
use Typemill\Static\Translations;
class Settings
{
public static function loadSettings()
{
echo debug_backtrace()[1]['function'];
die('use model load settings instead');
$defaultsettings = self::getDefaultSettings();
$usersettings = self::getUserSettings();
$settings = $defaultsettings;
$settings['setup'] = true;
if($usersettings)
{
$settings = array_merge($defaultsettings, $usersettings);
# make sure all image-size information are there
if(isset($usersettings['images']))
{
$images = array_merge($defaultsettings['images'], $settings['images']);
$settings['images'] = $images;
}
}
$settings['rootPath'] = getcwd();
$settings = self::addThemeSettings($settings);
return $settings;
}
public static function addThemeSettings($settings)
{
echo debug_backtrace()[1]['function'];
die('use model addThemeSettings instead');
# we have to check if the theme has been deleted
$rootpath = getcwd();
$themefolder = $rootpath . DIRECTORY_SEPARATOR . $settings['themeFolder'] . DIRECTORY_SEPARATOR;
# if there is no theme in settings or theme has been deleted
if(!isset($settings['theme']) OR !file_exists($themefolder . $settings['theme']))
{
# scan theme folder and get the first theme
$themes = array_filter(scandir($themefolder), function ($item) use($themefolder)
{
return is_dir($themefolder . $item) && strpos($item, '.') !== 0;
});
$firsttheme = reset($themes);
# if there is a theme with an index.twig-file
if($firsttheme && file_exists($themefolder . $firsttheme . DIRECTORY_SEPARATOR . 'index.twig'))
{
$settings['theme'] = $firsttheme;
}
else
{
die('You need at least one theme with an index.twig-file in your theme-folder.');
}
}
# We have the theme so create the theme path
$settings['themePath'] = $settings['rootPath'] . $settings['themeFolder'] . DIRECTORY_SEPARATOR . $settings['theme'];
# if there are no theme settings yet (e.g. no setup yet) use default theme settings
if(!isset($settings['themes']))
{
$themeSettings = self::getObjectSettings('themes', $settings['theme']);
$settings['themes'][$settings['theme']] = isset($themeSettings['settings']) ? $themeSettings['settings'] : false;
}
return $settings;
}
public static function getDefaultSettings()
{
echo debug_backtrace()[1]['function'];
die('use model getDefaultSettings instead');
$rootpath = getcwd();
$defaultsettingspath = $rootpath . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'typemill' . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR;
$defaultsettingsfile = $defaultsettingspath . 'defaults.yaml';
if(file_exists($defaultsettingsfile))
{
$defaultsettingsyaml = file_get_contents($defaultsettingsfile);
$defaultsettings = \Symfony\Component\Yaml\Yaml::parse($defaultsettingsyaml);
$defaultsettings['defaultSettingsPath'] = $defaultsettingspath;
return $defaultsettings;
}
return false;
}
public static function getUserSettings()
{
echo debug_backtrace()[1]['function'];
die('use model getUserSettings instead');
$rootpath = getcwd();
$usersettingsfile = $rootpath . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'settings.yaml';
if(file_exists($usersettingsfile))
{
$usersettingsyaml = file_get_contents($usersettingsfile);
$usersettings = \Symfony\Component\Yaml\Yaml::parse($usersettingsyaml);
return $usersettings;
}
return false;
}
public static function getObjectSettings($objectType, $objectName, $storagepath = '\Typemill\Models\Storage')
{
echo debug_backtrace()[1]['function'];
die('use model getObjectSettings instead');
$storage = new StorageWrapper($storagepath);
$objectSettings = $storage->getYaml($objectType, $objectName, $objectName . '.yaml');
if($objectSettings)
{
return $objectSettings;
}
return false;
/*
$rootpath = getcwd();
$objectfile = $rootpath . DIRECTORY_SEPARATOR . $objectType . DIRECTORY_SEPARATOR . $objectName . DIRECTORY_SEPARATOR . $objectName . '.yaml';
if(file_exists($objectfile))
{
$objectsettingsyaml = file_get_contents($objectfile);
$objectsettings = \Symfony\Component\Yaml\Yaml::parse($objectsettingsyaml);
return $objectsettings;
}
return false;
*/
}
public static function updateSettings(array $newSettings, $storagepath = '\Typemill\Models\Storage')
{
echo debug_backtrace()[1]['function'];
die('use model updateSettings instead');
$storage = new StorageWrapper($storagepath);
# only allow if usersettings already exists (setup has been done)
$userSettings = self::getUserSettings();
# merge usersettings with new settings
$settings = array_merge($userSettings, $newSettings);
$storage->updateYaml('settingsFolder', '', 'settings.yaml', $settings);
}
public static function getSettingsDefinitions($storagepath = '\Typemill\Models\Storage')
{
echo debug_backtrace()[1]['function'];
die('use model getSettingsDefinitions instead');
$storage = new StorageWrapper($storagepath);
return $storage->getYaml('systemSettings', '', 'system.yaml');
}
public static function createSettings($storagepath = '\Typemill\Models\Storage')
{
echo debug_backtrace()[1]['function'];
die('use model createSettings instead');
$storage = new StorageWrapper($storagepath);
$language = Translations::whichLanguage();
$initialSettings = $storage->updateYaml('settingsFolder', '', 'settings.yaml', [
'language' => $language
]);
if($initialSettings)
{
return true;
}
return false;
}
}

View File

@@ -208,10 +208,16 @@ const medialib = {
var self = this;
var itempath = false;
if(typeof data.item !== "undefined")
{
itempath = data.item.pathWithoutType;
}
tmaxios.get('/api/v1/pagemedia',{
params: {
'url': data.urlinfo.route,
'path': data.item.pathWithoutType
'path': itempath
}
})
.then(function (response)
@@ -339,10 +345,15 @@ const medialib = {
var imageself = this;
var itempath = false;
if(typeof data.item !== "undefined")
{
itempath = data.item.pathWithoutType;
}
tmaxios.get('/api/v1/images',{
params: {
'url': data.urlinfo.route,
'path': data.item.pathWithoutType
'path': itempath,
}
})
.then(function (response)

View File

@@ -54,5 +54,34 @@ $app->redirect('/tm/', $routeParser->urlFor('auth.show'), 302);
# downloads
$app->get('/media/files[/{params:.*}]', ControllerWebDownload::class . ':download')->setName('download.file');
foreach($routes as $pluginRoute)
{
$method = $pluginRoute['httpMethod'];
$route = $pluginRoute['route'];
$class = $pluginRoute['class'];
# $resource = isset($pluginRoute['resource']) ? $pluginRoute['resource'] : NULL;
# $privilege = isset($pluginRoute['privilege']) ? $pluginRoute['privilege'] : NULL;
# echo '<br>';
# echo 'method: ' . $method . ' -> route: ' . $route . ' -> class: ' . $class;
if(isset($pluginRoute['name']))
{
# $app->{$method}($route, $class)->setName($pluginRoute['name'])->add(new accessMiddleware($container['router'], $container['acl'], $resource, $privilege));
$app->{$method}($route, $class)->setName($pluginRoute['name']);
}
else
{
# $app->{$method}($route, $class)->add(new accessMiddleware($container['router'], $container['acl'], $resource, $privilege));
$app->{$method}($route, $class);
}
# if api and if authorization
# ->add(new ApiAuthorization($acl, 'account', 'view'));
# if web and if authorization
# ->add(new WebAuthorization($acl, 'account', 'view'));
}
# die();
# website
$app->get('/[{route:.*}]', ControllerWebFrontend::class . ':index')->setName('home');