mirror of
https://github.com/typemill/typemill.git
synced 2025-07-30 19:00:32 +02:00
refactored navigation model
This commit is contained in:
213
composer.lock
generated
213
composer.lock
generated
@@ -346,16 +346,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-permissions-acl",
|
||||
"version": "2.12.0",
|
||||
"version": "2.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-permissions-acl.git",
|
||||
"reference": "0d88f430953fbcbce382f09090db28905b90d60f"
|
||||
"reference": "86cecb540cf8f2e088d70d8acef1fc9203ed5023"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-permissions-acl/zipball/0d88f430953fbcbce382f09090db28905b90d60f",
|
||||
"reference": "0d88f430953fbcbce382f09090db28905b90d60f",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-permissions-acl/zipball/86cecb540cf8f2e088d70d8acef1fc9203ed5023",
|
||||
"reference": "86cecb540cf8f2e088d70d8acef1fc9203ed5023",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -366,11 +366,12 @@
|
||||
"zendframework/zend-permissions-acl": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-coding-standard": "~2.4.0",
|
||||
"laminas/laminas-coding-standard": "~2.5.0",
|
||||
"laminas/laminas-servicemanager": "^3.19",
|
||||
"phpunit/phpunit": "^9.5.25",
|
||||
"psalm/plugin-phpunit": "^0.17.0",
|
||||
"vimeo/psalm": "^4.29"
|
||||
"phpbench/phpbench": "^1.2",
|
||||
"phpunit/phpunit": "^9.5.26",
|
||||
"psalm/plugin-phpunit": "^0.18.0",
|
||||
"vimeo/psalm": "^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-servicemanager": "To support Laminas\\Permissions\\Acl\\Assertion\\AssertionManager plugin manager usage"
|
||||
@@ -405,20 +406,20 @@
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2022-10-17T04:26:35+00:00"
|
||||
"time": "2023-02-01T16:19:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v1.2.2",
|
||||
"version": "v1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/serializable-closure.git",
|
||||
"reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae"
|
||||
"reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/47afb7fae28ed29057fdca37e16a84f90cc62fae",
|
||||
"reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f23fe9d4e95255dacee1bf3525e0810d1a1b0f37",
|
||||
"reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -465,7 +466,7 @@
|
||||
"issues": "https://github.com/laravel/serializable-closure/issues",
|
||||
"source": "https://github.com/laravel/serializable-closure"
|
||||
},
|
||||
"time": "2022-09-08T13:45:54+00:00"
|
||||
"time": "2023-01-30T18:31:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
@@ -692,22 +693,22 @@
|
||||
},
|
||||
{
|
||||
"name": "php-di/slim-bridge",
|
||||
"version": "3.2.0",
|
||||
"version": "3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-DI/Slim-Bridge.git",
|
||||
"reference": "1644a2f31079e92a14cebbf90c7f71ebcbe39ee6"
|
||||
"reference": "9374b67ebf2f135b32c34907b7891b02b935d845"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-DI/Slim-Bridge/zipball/1644a2f31079e92a14cebbf90c7f71ebcbe39ee6",
|
||||
"reference": "1644a2f31079e92a14cebbf90c7f71ebcbe39ee6",
|
||||
"url": "https://api.github.com/repos/PHP-DI/Slim-Bridge/zipball/9374b67ebf2f135b32c34907b7891b02b935d845",
|
||||
"reference": "9374b67ebf2f135b32c34907b7891b02b935d845",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"php-di/invoker": "^2.0.0",
|
||||
"php-di/php-di": "^6.0.0",
|
||||
"php-di/php-di": "^6.0|^7.0",
|
||||
"slim/slim": "^4.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -727,9 +728,9 @@
|
||||
"description": "PHP-DI integration in Slim",
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-DI/Slim-Bridge/issues",
|
||||
"source": "https://github.com/PHP-DI/Slim-Bridge/tree/3.2.0"
|
||||
"source": "https://github.com/PHP-DI/Slim-Bridge/tree/3.3.0"
|
||||
},
|
||||
"time": "2021-11-01T16:14:12+00:00"
|
||||
"time": "2023-01-13T15:49:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -1147,30 +1148,30 @@
|
||||
},
|
||||
{
|
||||
"name": "slim/csrf",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim-Csrf.git",
|
||||
"reference": "ee811a258ecee807846aefc51aabc1963ae0a400"
|
||||
"reference": "ebaaf295fd6d7224078d8ae3bba45329b31798c7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim-Csrf/zipball/ee811a258ecee807846aefc51aabc1963ae0a400",
|
||||
"reference": "ee811a258ecee807846aefc51aabc1963ae0a400",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim-Csrf/zipball/ebaaf295fd6d7224078d8ae3bba45329b31798c7",
|
||||
"reference": "ebaaf295fd6d7224078d8ae3bba45329b31798c7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/http-server-handler": "^1.0",
|
||||
"psr/http-server-middleware": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/prophecy": "^1.12",
|
||||
"phpspec/prophecy": "^1.15",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"squizlabs/php_codesniffer": "^3.5.8"
|
||||
"squizlabs/php_codesniffer": "^3.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -1190,7 +1191,7 @@
|
||||
}
|
||||
],
|
||||
"description": "Slim Framework 4 CSRF protection PSR-15 middleware",
|
||||
"homepage": "http://slimframework.com",
|
||||
"homepage": "https://www.slimframework.com",
|
||||
"keywords": [
|
||||
"csrf",
|
||||
"framework",
|
||||
@@ -1199,9 +1200,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/slimphp/Slim-Csrf/issues",
|
||||
"source": "https://github.com/slimphp/Slim-Csrf/tree/1.2.1"
|
||||
"source": "https://github.com/slimphp/Slim-Csrf/tree/1.3.0"
|
||||
},
|
||||
"time": "2021-02-04T15:37:21+00:00"
|
||||
"time": "2022-11-05T19:27:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/flash",
|
||||
@@ -1257,40 +1258,40 @@
|
||||
},
|
||||
{
|
||||
"name": "slim/psr7",
|
||||
"version": "1.5",
|
||||
"version": "1.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim-Psr7.git",
|
||||
"reference": "a47b43a8da7c0208b4c228af0cb29ea36080635a"
|
||||
"reference": "3471c22c1a0d26c51c78f6aeb06489d38cf46a4d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim-Psr7/zipball/a47b43a8da7c0208b4c228af0cb29ea36080635a",
|
||||
"reference": "a47b43a8da7c0208b4c228af0cb29ea36080635a",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim-Psr7/zipball/3471c22c1a0d26c51c78f6aeb06489d38cf46a4d",
|
||||
"reference": "3471c22c1a0d26c51c78f6aeb06489d38cf46a4d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"fig/http-message-util": "^1.1.5",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"ralouphie/getallheaders": "^3.0",
|
||||
"symfony/polyfill-php80": "^1.23"
|
||||
"symfony/polyfill-php80": "^1.26"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-factory-implementation": "1.0",
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"adriansuter/php-autoload-override": "^1.2",
|
||||
"adriansuter/php-autoload-override": "^1.3",
|
||||
"ext-json": "*",
|
||||
"http-interop/http-factory-tests": "^0.9.0",
|
||||
"php-http/psr7-integration-tests": "dev-master",
|
||||
"phpspec/prophecy": "^1.14",
|
||||
"phpspec/prophecy": "^1.15",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpstan/phpstan": "^0.12.99",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
"squizlabs/php_codesniffer": "^3.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -1333,22 +1334,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/slimphp/Slim-Psr7/issues",
|
||||
"source": "https://github.com/slimphp/Slim-Psr7/tree/1.5"
|
||||
"source": "https://github.com/slimphp/Slim-Psr7/tree/1.6"
|
||||
},
|
||||
"time": "2021-09-22T04:33:00+00:00"
|
||||
"time": "2022-11-05T18:50:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "4.10.0",
|
||||
"version": "4.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0"
|
||||
"reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0",
|
||||
"reference": "0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7",
|
||||
"reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1363,21 +1364,21 @@
|
||||
"psr/log": "^1.1 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"adriansuter/php-autoload-override": "^1.2",
|
||||
"adriansuter/php-autoload-override": "^1.3",
|
||||
"ext-simplexml": "*",
|
||||
"guzzlehttp/psr7": "^2.1",
|
||||
"guzzlehttp/psr7": "^2.4",
|
||||
"httpsoft/http-message": "^1.0",
|
||||
"httpsoft/http-server-request": "^1.0",
|
||||
"laminas/laminas-diactoros": "^2.8",
|
||||
"laminas/laminas-diactoros": "^2.17",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"nyholm/psr7-server": "^1.0",
|
||||
"phpspec/prophecy": "^1.15",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"slim/http": "^1.2",
|
||||
"slim/psr7": "^1.5",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
"squizlabs/php_codesniffer": "^3.7"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-simplexml": "Needed to support XML format in BodyParsingMiddleware",
|
||||
@@ -1450,7 +1451,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-14T14:18:23+00:00"
|
||||
"time": "2022-11-06T16:33:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/twig-view",
|
||||
@@ -1519,16 +1520,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v6.0.9",
|
||||
"version": "v6.0.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "5c85b58422865d42c6eb46f7693339056db098a8"
|
||||
"reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/5c85b58422865d42c6eb46f7693339056db098a8",
|
||||
"reference": "5c85b58422865d42c6eb46f7693339056db098a8",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2eaf8e63bc5b8cefabd4a800157f0d0c094f677a",
|
||||
"reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1582,7 +1583,7 @@
|
||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v6.0.9"
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v6.0.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1598,7 +1599,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-05T16:45:52+00:00"
|
||||
"time": "2023-01-01T08:36:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
@@ -1681,16 +1682,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v6.0.11",
|
||||
"version": "v6.0.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "09cb683ba5720385ea6966e5e06be2a34f2568b1"
|
||||
"reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/09cb683ba5720385ea6966e5e06be2a34f2568b1",
|
||||
"reference": "09cb683ba5720385ea6966e5e06be2a34f2568b1",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/5cc9cac6586fc0c28cd173780ca696e419fefa11",
|
||||
"reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1722,7 +1723,7 @@
|
||||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v6.0.11"
|
||||
"source": "https://github.com/symfony/finder/tree/v6.0.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1738,20 +1739,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-29T07:39:48+00:00"
|
||||
"time": "2023-01-20T17:44:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1766,7 +1767,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -1804,7 +1805,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1820,20 +1821,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1848,7 +1849,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -1887,7 +1888,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1903,20 +1904,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1925,7 +1926,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -1970,7 +1971,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1986,20 +1987,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-10T07:21:04+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
|
||||
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
|
||||
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2008,7 +2009,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -2049,7 +2050,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2065,20 +2066,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v6.0.14",
|
||||
"version": "v6.0.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "e65020d137ad54beb85a67ffe6435e980f35ccf3"
|
||||
"reference": "deec3a812a0305a50db8ae689b183f43d915c884"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/e65020d137ad54beb85a67ffe6435e980f35ccf3",
|
||||
"reference": "e65020d137ad54beb85a67ffe6435e980f35ccf3",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/deec3a812a0305a50db8ae689b183f43d915c884",
|
||||
"reference": "deec3a812a0305a50db8ae689b183f43d915c884",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2123,7 +2124,7 @@
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v6.0.14"
|
||||
"source": "https://github.com/symfony/yaml/tree/v6.0.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2139,20 +2140,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-10-07T08:02:12+00:00"
|
||||
"time": "2023-01-11T11:50:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.4.3",
|
||||
"version": "v3.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
|
||||
"reference": "a6e0510cc793912b451fd40ab983a1d28f611c15"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a6e0510cc793912b451fd40ab983a1d28f611c15",
|
||||
"reference": "a6e0510cc793912b451fd40ab983a1d28f611c15",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2167,7 +2168,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
"dev-master": "3.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -2203,7 +2204,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.3"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.5.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2215,7 +2216,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-09-28T08:42:51+00:00"
|
||||
"time": "2023-02-08T07:49:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "vlucas/valitron",
|
||||
|
1
data/navigation/navi-draft.txt
Normal file
1
data/navigation/navi-draft.txt
Normal file
File diff suppressed because one or more lines are too long
66
data/navigation/navi-extended.txt
Normal file
66
data/navigation/navi-extended.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
/welcome:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome
|
||||
keyPath: 0
|
||||
/welcome/setup-your-website:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome/00-setup-your-website.md
|
||||
keyPath: '0.0'
|
||||
/welcome/manage-access:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome/01-manage-access.md
|
||||
keyPath: '0.1'
|
||||
/welcome/write-content:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome/02-write-content.md
|
||||
keyPath: '0.2'
|
||||
/welcome/get-help:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome/03-get-help.md
|
||||
keyPath: '0.3'
|
||||
/welcome/markdown-test:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome/04-markdown-test.md
|
||||
keyPath: '0.4'
|
||||
/cyanine-theme:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /01-cyanine-theme
|
||||
keyPath: 1
|
||||
/cyanine-theme/landingpage:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /01-cyanine-theme/00-landingpage.md
|
||||
keyPath: '1.0'
|
||||
/cyanine-theme/colors-and-fonts:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /01-cyanine-theme/01-colors-and-fonts.md
|
||||
keyPath: '1.1'
|
||||
/cyanine-theme/footer:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /01-cyanine-theme/02-footer.md
|
||||
keyPath: '1.2'
|
||||
/cyanine-theme/content-elements:
|
||||
navtitle: ''
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /01-cyanine-theme/03-content-elements.md
|
||||
keyPath: '1.3'
|
@@ -90,7 +90,6 @@ class ControllerData extends Controller
|
||||
return $allowedsystemnavi;
|
||||
}
|
||||
|
||||
|
||||
protected function getThemeDetails()
|
||||
{
|
||||
$themes = $this->getThemes();
|
||||
@@ -239,4 +238,157 @@ class ControllerData extends Controller
|
||||
|
||||
return $userfields;
|
||||
}
|
||||
|
||||
|
||||
|
||||
##########################################################################################
|
||||
# GET STUFF FOR EDITOR AREA
|
||||
##########################################################################################
|
||||
|
||||
# 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;
|
||||
}
|
||||
}
|
210
system/typemill/Controllers/ControllerWebAuthor.php
Normal file
210
system/typemill/Controllers/ControllerWebAuthor.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Controllers;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Slim\Routing\RouteContext;
|
||||
# use Typemill\Models\Folder;
|
||||
# use Typemill\Extensions\ParsedownExtension;
|
||||
# use Typemill\Models\StorageWrapper;
|
||||
# use Typemill\Models\User;
|
||||
# use Typemill\Models\License;
|
||||
|
||||
use Typemill\Models\Navigation;
|
||||
|
||||
class ControllerWebAuthor extends Controller
|
||||
{
|
||||
public function showBlox(Request $request, Response $response, $args)
|
||||
{
|
||||
# get url for requested page
|
||||
$url = isset($args['route']) ? '/' . $args['route'] : '/';
|
||||
$urlinfo = $this->c->get('urlinfo');
|
||||
$fullUrl = $urlinfo['baseurl'] . $url;
|
||||
$langattr = $this->settings['langattr'];
|
||||
|
||||
$navigation = new Navigation();
|
||||
|
||||
$extendedNavigation = $navigation->getExtendedNavigation($urlinfo, $langattr);
|
||||
$pageinfo = $extendedNavigation[$url] ?? false;
|
||||
|
||||
if(!$pageinfo)
|
||||
{
|
||||
return $this->c->get('view')->render($response->withStatus(404), '404.twig', [
|
||||
'title' => 'Typemill Author Area',
|
||||
'description' => 'Typemill Version 2 wird noch besser als Version 1.'
|
||||
]);
|
||||
}
|
||||
|
||||
# extend : $request->getAttribute('c_userrole')
|
||||
$draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr);
|
||||
|
||||
$item = $navigation->getItemWithKeyPath($draftNavigation, explode(".", $pageinfo['keyPath']));
|
||||
|
||||
$mainNavigation = $navigation->getMainNavigation($request->getAttribute('c_userrole'), $this->c->get('acl'), $urlinfo, $this->settings['editor']);
|
||||
|
||||
return $this->c->get('view')->render($response, 'content/blox-editor.twig', [
|
||||
'settings' => $this->settings,
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'settings' => $this->settings,
|
||||
'navigation' => $draftNavigation,
|
||||
'item' => $item,
|
||||
'urlinfo' => $urlinfo
|
||||
]
|
||||
]);
|
||||
|
||||
echo '<pre>';
|
||||
print_r($draftNavigation);
|
||||
die();
|
||||
|
||||
|
||||
|
||||
# set structure
|
||||
if(!$this->setStructureDraft()){ return $this->renderIntern404($response, array( 'navigation' => true, 'content' => $this->errors )); }
|
||||
|
||||
# set information for homepage
|
||||
$this->setHomepage($args);
|
||||
|
||||
# set item
|
||||
if(!$this->setItem()){ return $this->renderIntern404($response, array( 'navigation' => $this->structureDraft, 'settings' => $this->settings, 'content' => $this->errors )); }
|
||||
|
||||
# we have to check ownership here to use it for permission-check in templates
|
||||
$this->checkContentOwnership();
|
||||
|
||||
# set the status for published and drafted
|
||||
$this->setPublishStatus();
|
||||
|
||||
# set path
|
||||
$this->setItemPath($this->item->fileType);
|
||||
|
||||
# add the modified date for the file
|
||||
$this->item->modified = ($this->item->published OR $this->item->drafted) ? filemtime($this->settings['contentFolder'] . $this->path) : false;
|
||||
|
||||
# read content from file
|
||||
if(!$this->setContent()){ return $this->renderIntern404($response, array( 'navigation' => $this->structure, 'settings' => $this->settings, 'content' => $this->errors )); }
|
||||
|
||||
$content = $this->content;
|
||||
|
||||
if($content == '')
|
||||
{
|
||||
$content = [];
|
||||
}
|
||||
|
||||
# initialize parsedown extension
|
||||
$parsedown = new ParsedownExtension($this->uri->getBaseUrl());
|
||||
|
||||
# to fix footnote-logic in parsedown, set visual mode to true
|
||||
$parsedown->setVisualMode();
|
||||
|
||||
# if content is not an array, then transform it
|
||||
if(!is_array($content))
|
||||
{
|
||||
# turn markdown into an array of markdown-blocks
|
||||
$content = $parsedown->markdownToArrayBlocks($content);
|
||||
}
|
||||
|
||||
# needed for ToC links
|
||||
$relurl = '/tm/content/' . $this->settings['editor'] . '/' . $this->item->urlRel;
|
||||
|
||||
foreach($content as $key => $block)
|
||||
{
|
||||
/* parse markdown-file to content-array */
|
||||
$contentArray = $parsedown->text($block);
|
||||
|
||||
/* parse markdown-content-array to content-string */
|
||||
$content[$key] = $parsedown->markup($contentArray);
|
||||
}
|
||||
|
||||
# extract title and delete from content array, array will start at 1 after that.
|
||||
$title = '# add title';
|
||||
if(isset($content[0]))
|
||||
{
|
||||
$title = $content[0];
|
||||
unset($content[0]);
|
||||
}
|
||||
|
||||
return $this->renderIntern($response, 'editor/editor-blox.twig', array(
|
||||
'acl' => $this->c->acl,
|
||||
'mycontent' => $this->mycontent,
|
||||
'navigation' => $this->structureDraft,
|
||||
'homepage' => $this->homepage,
|
||||
'title' => $title,
|
||||
'content' => $content,
|
||||
'item' => $this->item,
|
||||
'settings' => $this->settings
|
||||
));
|
||||
}
|
||||
|
||||
public function showContent(Request $request, Response $response, $args)
|
||||
{
|
||||
# get params from call
|
||||
# $this->uri = $request->getUri()->withUserInfo('');
|
||||
# $this->params = isset($args['params']) ? ['url' => $this->uri->getBasePath() . '/' . $args['params']] : ['url' => $this->uri->getBasePath()];
|
||||
|
||||
# set structure
|
||||
if(!$this->setStructureDraft()){ return $this->renderIntern404($response, array( 'navigation' => true, 'content' => $this->errors )); }
|
||||
|
||||
# set information for homepage
|
||||
$this->setHomepage($args);
|
||||
|
||||
# set item
|
||||
if(!$this->setItem()){ return $this->renderIntern404($response, array( 'navigation' => $this->structure, 'settings' => $this->settings, 'content' => $this->errors )); }
|
||||
|
||||
# we have to check ownership here to use it for permission-check in tempates
|
||||
$this->checkContentOwnership();
|
||||
|
||||
# get the breadcrumb (here we need it only to mark the actual item active in navigation)
|
||||
$breadcrumb = isset($this->item->keyPathArray) ? Folder::getBreadcrumb($this->structureDraft, $this->item->keyPathArray) : false;
|
||||
|
||||
# set the status for published and drafted
|
||||
$this->setPublishStatus();
|
||||
|
||||
# set path
|
||||
$this->setItemPath($this->item->fileType);
|
||||
|
||||
# add the modified date for the file
|
||||
$this->item->modified = ($this->item->published OR $this->item->drafted) ? filemtime($this->settings['contentFolder'] . $this->path) : false;
|
||||
|
||||
# read content from file
|
||||
if(!$this->setContent()){ return $this->renderIntern404($response, array( 'navigation' => $this->structure, 'settings' => $this->settings, 'content' => $this->errors )); }
|
||||
|
||||
$content = $this->content;
|
||||
$title = false;
|
||||
|
||||
# if content is an array, then it is a draft
|
||||
if(is_array($content))
|
||||
{
|
||||
# transform array to markdown
|
||||
$parsedown = new ParsedownExtension($this->uri->getBaseUrl());
|
||||
$content = $parsedown->arrayBlocksToMarkdown($content);
|
||||
}
|
||||
|
||||
# if there is content
|
||||
if($content != '')
|
||||
{
|
||||
# normalize linebreaks
|
||||
$content = str_replace(array("\r\n", "\r"), "\n", $content);
|
||||
$content = trim($content, "\n");
|
||||
|
||||
# and strip out title
|
||||
if($content[0] == '#')
|
||||
{
|
||||
$contentParts = explode("\n", $content, 2);
|
||||
$title = trim($contentParts[0], "# \t\n\r\0\x0B");
|
||||
$content = trim($contentParts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderIntern($response, 'editor/editor-raw.twig', array(
|
||||
'acl' => $this->c->acl,
|
||||
'mycontent' => $this->mycontent,
|
||||
'navigation' => $this->structureDraft,
|
||||
'homepage' => $this->homepage,
|
||||
'title' => $title,
|
||||
'content' => $content,
|
||||
'item' => $this->item,
|
||||
'settings' => $this->settings
|
||||
));
|
||||
}
|
||||
}
|
652
system/typemill/Models/Folder.php
Normal file
652
system/typemill/Models/Folder.php
Normal file
@@ -0,0 +1,652 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Models;
|
||||
|
||||
use \URLify;
|
||||
|
||||
class Folder
|
||||
{
|
||||
|
||||
/*
|
||||
* scans content of a folder (without recursion)
|
||||
* vars: folder path as string
|
||||
* returns: one-dimensional array with names of folders and files
|
||||
*/
|
||||
public function scanFolderFlat($folderPath)
|
||||
{
|
||||
$folderItems = scandir($folderPath);
|
||||
$folderContent = array();
|
||||
|
||||
foreach ($folderItems as $key => $item)
|
||||
{
|
||||
if (!in_array($item, array(".","..")))
|
||||
{
|
||||
$nameParts = $this->getStringParts($item);
|
||||
$fileType = array_pop($nameParts);
|
||||
|
||||
if($fileType == 'md' OR $fileType == 'txt' )
|
||||
{
|
||||
$folderContent[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $folderContent;
|
||||
}
|
||||
|
||||
/*
|
||||
* scans content of a folder recursively
|
||||
* vars: folder path as string
|
||||
* returns: multi-dimensional array with names of folders and files
|
||||
*/
|
||||
public function scanFolder($folderPath, $draft = false)
|
||||
{
|
||||
$folderItems = scandir($folderPath);
|
||||
$folderContent = array();
|
||||
|
||||
# if it is the live version and if it is a folder that is not published, then do not show the folder and its content.
|
||||
if(!$draft && !in_array('index.md', $folderItems)){ return false; }
|
||||
|
||||
foreach ($folderItems as $key => $item)
|
||||
{
|
||||
if (!in_array($item, array(".","..")) && substr($item, 0, 1) != '.')
|
||||
{
|
||||
if (is_dir($folderPath . DIRECTORY_SEPARATOR . $item))
|
||||
{
|
||||
|
||||
$subFolder = $item;
|
||||
$folderPublished = file_exists($folderPath . DIRECTORY_SEPARATOR . $item . DIRECTORY_SEPARATOR . 'index.md');
|
||||
|
||||
# scan that folder only if it is a draft or if the folder is published (contains index.md)
|
||||
if($draft OR $folderPublished)
|
||||
{
|
||||
$folderContent[$subFolder] = $this->scanFolder($folderPath . DIRECTORY_SEPARATOR . $subFolder, $draft);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$nameParts = $this->getStringParts($item);
|
||||
$fileType = array_pop($nameParts);
|
||||
|
||||
if($fileType == 'md')
|
||||
{
|
||||
$folderContent[] = $item;
|
||||
}
|
||||
|
||||
if($draft === true && $fileType == 'txt')
|
||||
{
|
||||
if(isset($last) && ($last == implode($nameParts)) )
|
||||
{
|
||||
array_pop($folderContent);
|
||||
$item = $item . 'md';
|
||||
}
|
||||
$folderContent[] = $item;
|
||||
}
|
||||
|
||||
/* store the name of the last file */
|
||||
$last = implode($nameParts);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $folderContent;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transforms array of folder item into an array of item-objects with additional information for each item
|
||||
* vars: multidimensional array with folder- and file-names
|
||||
* returns: array of objects. Each object contains information about an item (file or folder).
|
||||
*/
|
||||
|
||||
public function getFolderContentDetails(array $folderContent, $language, $baseUrl, $fullSlugWithFolder = NULL, $fullSlugWithoutFolder = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
|
||||
{
|
||||
$contentDetails = [];
|
||||
$iteration = 0;
|
||||
$chapternr = 1;
|
||||
|
||||
foreach($folderContent as $key => $name)
|
||||
{
|
||||
$item = new \stdClass();
|
||||
|
||||
if(is_array($name))
|
||||
{
|
||||
$nameParts = $this->getStringParts($key);
|
||||
|
||||
$fileType = '';
|
||||
if(in_array('index.md', $name))
|
||||
{
|
||||
$fileType = 'md';
|
||||
$status = 'published';
|
||||
}
|
||||
if(in_array('index.txt', $name))
|
||||
{
|
||||
$fileType = 'txt';
|
||||
$status = 'unpublished';
|
||||
}
|
||||
if(in_array('index.txtmd', $name))
|
||||
{
|
||||
$fileType = 'txt';
|
||||
$status = 'modified';
|
||||
}
|
||||
|
||||
$item->originalName = $key;
|
||||
$item->elementType = 'folder';
|
||||
$item->contains = $this->getFolderContentType($name, $fullPath . DIRECTORY_SEPARATOR . $key . DIRECTORY_SEPARATOR . 'index.yaml');
|
||||
$item->status = $status;
|
||||
$item->fileType = $fileType;
|
||||
$item->order = count($nameParts) > 1 ? array_shift($nameParts) : NULL;
|
||||
$item->name = implode(" ",$nameParts);
|
||||
$item->name = iconv(mb_detect_encoding($item->name, mb_detect_order(), true), "UTF-8", $item->name);
|
||||
$item->slug = implode("-",$nameParts);
|
||||
$item->slug = $this->createSlug($item->slug, $language);
|
||||
$item->path = $fullPath . DIRECTORY_SEPARATOR . $key;
|
||||
$item->pathWithoutType = $fullPath . DIRECTORY_SEPARATOR . $key . DIRECTORY_SEPARATOR . 'index';
|
||||
$item->urlRelWoF = $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
$item->urlRel = $fullSlugWithFolder . '/' . $item->slug;
|
||||
$item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
$item->key = $iteration;
|
||||
$item->keyPath = isset($keyPath) ? $keyPath . '.' . $iteration : $iteration;
|
||||
$item->keyPathArray = explode('.', $item->keyPath);
|
||||
$item->chapter = $chapter ? $chapter . '.' . $chapternr : $chapternr;
|
||||
$item->active = false;
|
||||
$item->activeParent = false;
|
||||
$item->hide = false;
|
||||
|
||||
# sort posts in descending order
|
||||
if($item->contains == "posts")
|
||||
{
|
||||
rsort($name);
|
||||
}
|
||||
|
||||
$item->folderContent = $this->getFolderContentDetails($name, $language, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter);
|
||||
}
|
||||
elseif($name)
|
||||
{
|
||||
# do not use files in base folder (only folders are allowed)
|
||||
# if(!isset($keyPath)) continue;
|
||||
|
||||
# do not use index files
|
||||
if($name == 'index.md' || $name == 'index.txt' || $name == 'index.txtmd' ) continue;
|
||||
|
||||
$nameParts = $this->getStringParts($name);
|
||||
$fileType = array_pop($nameParts);
|
||||
$nameWithoutType = $this->getNameWithoutType($name);
|
||||
|
||||
if($fileType == 'md')
|
||||
{
|
||||
$status = 'published';
|
||||
}
|
||||
elseif($fileType == 'txt')
|
||||
{
|
||||
$status = 'unpublished';
|
||||
}
|
||||
else
|
||||
{
|
||||
$fileType = 'txt';
|
||||
$status = 'modified';
|
||||
}
|
||||
|
||||
$item->originalName = $name;
|
||||
$item->elementType = 'file';
|
||||
$item->status = $status;
|
||||
$item->fileType = $fileType;
|
||||
$item->order = count($nameParts) > 1 ? array_shift($nameParts) : NULL;
|
||||
$item->name = implode(" ",$nameParts);
|
||||
$item->name = iconv(mb_detect_encoding($item->name, mb_detect_order(), true), "UTF-8", $item->name);
|
||||
$item->slug = implode("-",$nameParts);
|
||||
$item->slug = $this->createSlug($item->slug, $language);
|
||||
$item->path = $fullPath . DIRECTORY_SEPARATOR . $name;
|
||||
$item->pathWithoutType = $fullPath . DIRECTORY_SEPARATOR . $nameWithoutType;
|
||||
$item->key = $iteration;
|
||||
$item->keyPath = isset($keyPath) ? $keyPath . '.' . $iteration : $iteration;
|
||||
$item->keyPathArray = explode('.',$item->keyPath);
|
||||
$item->chapter = $chapter . '.' . $chapternr;
|
||||
$item->urlRelWoF = $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
$item->urlRel = $fullSlugWithFolder . '/' . $item->slug;
|
||||
$item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
$item->active = false;
|
||||
$item->activeParent = false;
|
||||
$item->hide = false;
|
||||
}
|
||||
|
||||
$iteration++;
|
||||
$chapternr++;
|
||||
$contentDetails[] = $item;
|
||||
}
|
||||
return $contentDetails;
|
||||
}
|
||||
|
||||
public function getFolderContentType($folder, $yamlpath)
|
||||
{
|
||||
# check if folder is empty or has only index.yaml-file. This is a rare case so make it quick and dirty
|
||||
if(count($folder) == 1)
|
||||
{
|
||||
# check if in folder yaml file contains "posts", then return posts
|
||||
$folderyamlpath = getcwd() . DIRECTORY_SEPARATOR . 'content' . DIRECTORY_SEPARATOR . $yamlpath;
|
||||
|
||||
$fileContent = false;
|
||||
if(file_exists($folderyamlpath))
|
||||
{
|
||||
$fileContent = file_get_contents($folderyamlpath);
|
||||
}
|
||||
|
||||
if($fileContent && strpos($fileContent, 'contains: posts') !== false)
|
||||
{
|
||||
return 'posts';
|
||||
}
|
||||
return 'pages';
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $folder[0];
|
||||
$nameParts = $this->getStringParts($file);
|
||||
$order = count($nameParts) > 1 ? array_shift($nameParts) : NULL;
|
||||
$order = substr($order, 0, 7);
|
||||
|
||||
if(\DateTime::createFromFormat('Ymd', $order) !== FALSE)
|
||||
{
|
||||
return "posts";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "pages";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getHomepageItem($baseUrl)
|
||||
{
|
||||
# return a standard item-object
|
||||
$item = new \stdClass;
|
||||
|
||||
$item->status = 'published';
|
||||
$item->originalName = 'home';
|
||||
$item->elementType = 'folder';
|
||||
$item->fileType = 'md';
|
||||
$item->order = false;
|
||||
$item->name = 'home';
|
||||
$item->slug = '';
|
||||
$item->path = '';
|
||||
$item->pathWithoutType = DIRECTORY_SEPARATOR . 'index';
|
||||
$item->key = false;
|
||||
$item->keyPath = false;
|
||||
$item->keyPathArray = false;
|
||||
$item->chapter = false;
|
||||
$item->urlRel = '/';
|
||||
$item->urlRelWoF = '/';
|
||||
$item->urlAbs = $baseUrl;
|
||||
$item->name = 'home';
|
||||
$item->active = false;
|
||||
$item->activeParent = false;
|
||||
$item->hide = false;
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function getItemForUrl($folderContentDetails, $url, $baseUrl, $result = NULL, $home = NULL )
|
||||
{
|
||||
# if we are on the homepage
|
||||
if($home)
|
||||
{
|
||||
return $this->getHomepageItem($baseUrl);
|
||||
}
|
||||
|
||||
foreach($folderContentDetails as $key => $item)
|
||||
{
|
||||
# set item active, needed to move item in navigation
|
||||
if($item->urlRel === $url)
|
||||
{
|
||||
$item->active = true;
|
||||
$result = $item;
|
||||
}
|
||||
elseif($item->elementType === "folder")
|
||||
{
|
||||
$result = $this->getItemForUrl($item->folderContent, $url, $baseUrl, $result);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getItemForUrlFrontend($folderContentDetails, $url, $result = NULL)
|
||||
{
|
||||
foreach($folderContentDetails as $key => $item)
|
||||
{
|
||||
# set item active, needed to move item in navigation
|
||||
if($item->urlRelWoF === $url)
|
||||
{
|
||||
$item->active = true;
|
||||
$result = $item;
|
||||
}
|
||||
elseif($item->elementType === "folder")
|
||||
{
|
||||
$result = $this->getItemForUrlFrontend($item->folderContent, $url, $result);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getPagingForItem($content, $item)
|
||||
{
|
||||
# if page is home
|
||||
if(trim($item->pathWithoutType, DIRECTORY_SEPARATOR) == 'index')
|
||||
{
|
||||
return $item;
|
||||
}
|
||||
|
||||
$keyPos = count($item->keyPathArray)-1;
|
||||
$thisChapArray = $item->keyPathArray;
|
||||
$nextItemArray = $item->keyPathArray;
|
||||
$prevItemArray = $item->keyPathArray;
|
||||
|
||||
$item->thisChapter = false;
|
||||
$item->prevItem = false;
|
||||
$item->nextItem = false;
|
||||
|
||||
|
||||
/************************
|
||||
* ADD THIS CHAPTER *
|
||||
************************/
|
||||
|
||||
if($keyPos > 0)
|
||||
{
|
||||
array_pop($thisChapArray);
|
||||
$item->thisChapter = $this->getItemWithKeyPath($content, $thisChapArray);
|
||||
}
|
||||
|
||||
/************************
|
||||
* ADD NEXT ITEM *
|
||||
************************/
|
||||
|
||||
if($item->elementType == 'folder')
|
||||
{
|
||||
# get the first element in the folder
|
||||
$item->nextItem = isset($item->folderContent[0]) ? clone($item->folderContent[0]) : false;
|
||||
}
|
||||
|
||||
# the item is a file or an empty folder
|
||||
if(!$item->nextItem)
|
||||
{
|
||||
# walk to the next file in the same hierarchy
|
||||
$nextItemArray[$keyPos]++;
|
||||
|
||||
# get the key of the last element in this hierarchy level
|
||||
# if there is no chapter, then it is probably an empty first-level-folder. Count content to get the number of first level items
|
||||
$lastKey = $item->thisChapter ? array_key_last($item->thisChapter->folderContent) : count($content);
|
||||
|
||||
# as long as the nextItemArray is smaller than the last key in this hierarchy level, search for the next item
|
||||
# this ensures that it does not stop if key is missing (e.g. if the next page is hidden)
|
||||
while( ($nextItemArray[$keyPos] <= $lastKey) && !$item->nextItem = $this->getItemWithKeyPath($content, $nextItemArray) )
|
||||
{
|
||||
$nextItemArray[$keyPos]++;
|
||||
}
|
||||
}
|
||||
|
||||
# there is no next file or folder in this level, so walk up the hierarchy to the next folder or file
|
||||
while(!$item->nextItem)
|
||||
{
|
||||
# delete the array level with the current item, so you are in the parent folder
|
||||
array_pop($nextItemArray);
|
||||
|
||||
# if the array is empty now, then you where in the base level already, so break
|
||||
if(empty($nextItemArray)) break;
|
||||
|
||||
# define the key position where you are right now
|
||||
$newKeyPos = count($nextItemArray)-1;
|
||||
|
||||
# go to the next position
|
||||
$nextItemArray[$newKeyPos]++;
|
||||
|
||||
# search for 5 items in case there are some hidden elements
|
||||
$maxlength = $nextItemArray[$newKeyPos]+5;
|
||||
while( ($nextItemArray[$newKeyPos] <= $maxlength) && !$item->nextItem = $this->getItemWithKeyPath($content, $nextItemArray) )
|
||||
{
|
||||
$nextItemArray[$newKeyPos]++;
|
||||
}
|
||||
}
|
||||
|
||||
/************************
|
||||
* ADD PREVIOUS ITEM *
|
||||
************************/
|
||||
|
||||
# check if element is the first in the array
|
||||
$first = ($prevItemArray[$keyPos] == 0) ? true : false;
|
||||
|
||||
if(!$first)
|
||||
{
|
||||
$prevItemArray[$keyPos]--;
|
||||
|
||||
while($prevItemArray[$keyPos] >= 0 && !$item->prevItem = $this->getItemWithKeyPath($content, $prevItemArray))
|
||||
{
|
||||
$prevItemArray[$keyPos]--;
|
||||
}
|
||||
|
||||
# if no item is found, then all previous items are hidden, so set first item to true and it will walk up the array later
|
||||
if(!$item->prevItem)
|
||||
{
|
||||
$first = true;
|
||||
}
|
||||
elseif($item->prevItem && $item->prevItem->elementType == 'folder' && !empty($item->prevItem->folderContent))
|
||||
{
|
||||
# if the previous item is a folder, the get the last item of that folder
|
||||
$item->prevItem = $this->getLastItemOfFolder($item->prevItem);
|
||||
}
|
||||
}
|
||||
|
||||
# if it is the first item in the folder (or all other files are hidden)
|
||||
if($first)
|
||||
{
|
||||
# then the previous item is the containing chapter
|
||||
$item->prevItem = $item->thisChapter;
|
||||
}
|
||||
|
||||
if($item->prevItem && $item->prevItem->elementType == 'folder'){ unset($item->prevItem->folderContent); }
|
||||
if($item->nextItem && $item->nextItem->elementType == 'folder'){ unset($item->nextItem->folderContent); }
|
||||
if($item->thisChapter){unset($item->thisChapter->folderContent); }
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets a copy of an item with a key
|
||||
* @param array $content with the full structure of the content as multidimensional array
|
||||
* @param array $searchArray with the key as a one-dimensional array like array(0,3,4)
|
||||
* @return array $item
|
||||
*/
|
||||
|
||||
|
||||
# copy this to navigation
|
||||
# add keypath to the extended index
|
||||
|
||||
public function getItemWithKeyPath($content, array $searchArray)
|
||||
{
|
||||
$item = false;
|
||||
|
||||
foreach($searchArray as $key => $itemKey)
|
||||
{
|
||||
$item = isset($content[$itemKey]) ? clone($content[$itemKey]) : false;
|
||||
|
||||
unset($searchArray[$key]);
|
||||
if(!empty($searchArray) && $item)
|
||||
{
|
||||
return $this->getItemWithKeyPath($item->folderContent, $searchArray);
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
# https://www.quora.com/Learning-PHP-Is-there-a-way-to-get-the-value-of-multi-dimensional-array-by-specifying-the-key-with-a-variable
|
||||
# NOT IN USE
|
||||
public function getItemWithKeyPathNew($array, array $keys)
|
||||
{
|
||||
$item = $array;
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
$item = isset($item[$key]->folderContent) ? $item[$key]->folderContent : $item[$key];
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extracts an item with a key https://stackoverflow.com/questions/52097092/php-delete-value-of-array-with-dynamic-key
|
||||
* @param array $content with the full structure of the content as multidimensional array
|
||||
* @param array $searchArray with the key as a one-dimensional array like array(0,3,4)
|
||||
* @return array $item
|
||||
* NOT IN USE ??
|
||||
*/
|
||||
|
||||
public function extractItemWithKeyPath($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 array('structure' => $structure, 'item' => $item);
|
||||
}
|
||||
|
||||
# NOT IN USE
|
||||
public function deleteItemWithKeyPathNOTINUSE($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
|
||||
# mark parent element in original
|
||||
public function getBreadcrumb($content, $searchArray, $i = NULL, $breadcrumb = NULL)
|
||||
{
|
||||
# if it is the first round, create an empty array
|
||||
if(!$i){ $i = 0; $breadcrumb = array();}
|
||||
|
||||
if(!$searchArray){ return $breadcrumb;}
|
||||
|
||||
while($i < count($searchArray))
|
||||
{
|
||||
if(!isset($content[$searchArray[$i]])){ return false; }
|
||||
$item = $content[$searchArray[$i]];
|
||||
|
||||
if($i == count($searchArray)-1)
|
||||
{
|
||||
$item->active = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$item->activeParent = true;
|
||||
}
|
||||
|
||||
/*
|
||||
$item->active = true;
|
||||
if($i == count($searchArray)-2)
|
||||
{
|
||||
$item->activeParent = true;
|
||||
}
|
||||
*/
|
||||
|
||||
$copy = clone($item);
|
||||
if($copy->elementType == 'folder')
|
||||
{
|
||||
unset($copy->folderContent);
|
||||
$content = $item->folderContent;
|
||||
}
|
||||
$breadcrumb[] = $copy;
|
||||
|
||||
$i++;
|
||||
return $this->getBreadcrumb($content, $searchArray, $i++, $breadcrumb);
|
||||
}
|
||||
return $breadcrumb;
|
||||
}
|
||||
|
||||
public function getParentItem($content, $searchArray, $iteration = NULL)
|
||||
{
|
||||
if(!$iteration){ $iteration = 0; }
|
||||
while($iteration < count($searchArray)-2)
|
||||
{
|
||||
$content = $content[$searchArray[$iteration]]->folderContent;
|
||||
$iteration++;
|
||||
return $this->getParentItem($content, $searchArray, $iteration);
|
||||
}
|
||||
return $content[$searchArray[$iteration]];
|
||||
}
|
||||
|
||||
private function getLastItemOfFolder($folder)
|
||||
{
|
||||
$lastItem = end($folder->folderContent);
|
||||
if(is_object($lastItem) && $lastItem->elementType == 'folder' && !empty($lastItem->folderContent))
|
||||
{
|
||||
return $this->getLastItemOfFolder($lastItem);
|
||||
}
|
||||
return $lastItem;
|
||||
}
|
||||
|
||||
public function getStringParts($name)
|
||||
{
|
||||
return preg_split('/[\-\.\_\=\+\?\!\*\#\(\)\/ ]/',$name);
|
||||
}
|
||||
|
||||
public function getFileType($fileName)
|
||||
{
|
||||
$parts = preg_split('/\./',$fileName);
|
||||
return end($parts);
|
||||
}
|
||||
|
||||
public function splitFileName($fileName)
|
||||
{
|
||||
$parts = preg_split('/\./',$fileName);
|
||||
return $parts;
|
||||
}
|
||||
|
||||
public function getNameWithoutType($fileName)
|
||||
{
|
||||
$parts = preg_split('/\./',$fileName);
|
||||
return $parts[0];
|
||||
}
|
||||
|
||||
public function createSlug($name, $language = null)
|
||||
{
|
||||
$name = iconv(mb_detect_encoding($name, mb_detect_order(), true), "UTF-8", $name);
|
||||
$language = $language ? $language : "";
|
||||
|
||||
return URLify::filter(
|
||||
$name,
|
||||
$length = 60,
|
||||
$language,
|
||||
$file_name = false,
|
||||
$use_remove_list = false,
|
||||
$lower_case = true,
|
||||
$treat_underscore_as_space = true
|
||||
);
|
||||
}
|
||||
}
|
341
system/typemill/Models/Navigation.php
Normal file
341
system/typemill/Models/Navigation.php
Normal file
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Models;
|
||||
|
||||
use Typemill\Models\StorageWrapper;
|
||||
use Typemill\Models\Folder;
|
||||
|
||||
class Navigation
|
||||
{
|
||||
private $storage;
|
||||
|
||||
private $naviFolder;
|
||||
|
||||
private $liveNaviName;
|
||||
|
||||
private $draftNaviName;
|
||||
|
||||
private $extendedNaviName;
|
||||
|
||||
private $extendedNavigation = false;
|
||||
|
||||
private $draftNavigation = false;
|
||||
|
||||
private $basicDraftNavigation = false;
|
||||
|
||||
private $liveNavigation = false;
|
||||
|
||||
private $basicLiveNavigation = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->storage = new StorageWrapper('\Typemill\Models\Storage');
|
||||
|
||||
$this->naviFolder = 'data' . DIRECTORY_SEPARATOR . 'navigation';
|
||||
|
||||
$this->liveNaviName = 'navi-live.txt';
|
||||
|
||||
$this->draftNaviName = 'navi-draft.txt';
|
||||
|
||||
$this->extendedNaviName = 'navi-extended.txt';
|
||||
}
|
||||
|
||||
public function getMainNavigation($userrole, $acl, $urlinfo, $editor)
|
||||
{
|
||||
$mainnavi = $this->storage->getYaml('system/typemill/settings', 'mainnavi.yaml');
|
||||
|
||||
$allowedmainnavi = [];
|
||||
|
||||
foreach($mainnavi as $name => $naviitem)
|
||||
{
|
||||
if($acl->isAllowed($userrole, $naviitem['aclresource'], $naviitem['aclprivilege']))
|
||||
{
|
||||
# set the navi of current route active
|
||||
$thisRoute = '/tm/' . $name;
|
||||
if(strpos($urlinfo['route'], $thisRoute) !== false)
|
||||
{
|
||||
$naviitem['active'] = true;
|
||||
}
|
||||
|
||||
$allowedmainnavi[$name] = $naviitem;
|
||||
}
|
||||
}
|
||||
|
||||
# if system is there, then we do not need the account item
|
||||
if(isset($allowedmainnavi['system']))
|
||||
{
|
||||
unset($allowedmainnavi['account']);
|
||||
}
|
||||
|
||||
# set correct editor mode according to user settings
|
||||
if(isset($allowedmainnavi['content']) && $editor == 'raw')
|
||||
{
|
||||
$allowedmainnavi['content']['routename'] = "content.raw";
|
||||
}
|
||||
|
||||
return $allowedmainnavi;
|
||||
}
|
||||
|
||||
|
||||
# get the navigation with draft files for author environment
|
||||
public function getDraftNavigation($urlinfo, $language, $userrole = null, $username = null)
|
||||
{
|
||||
# todo: filter for userrole or username
|
||||
|
||||
$this->draftNavigation = $this->storage->getFile($this->naviFolder, $this->draftNaviName, 'unserialize');
|
||||
|
||||
if($this->draftNavigation)
|
||||
{
|
||||
return $this->draftNavigation;
|
||||
}
|
||||
|
||||
# if there is no cached navi, create a basic new draft navi
|
||||
$basicDraftNavigation = $this->getBasicDraftNavigation($urlinfo, $language);
|
||||
|
||||
# get the extended navigation with additional infos from the meta-files like title or hidden pages
|
||||
$extendedNavigation = $this->getExtendedNavigation($urlinfo, $language);
|
||||
|
||||
# merge the basic draft navi with the extended infos from meta-files
|
||||
$draftNavigation = $this->mergeNavigationWithExtended($basicDraftNavigation, $extendedNavigation);
|
||||
|
||||
# cache it
|
||||
$this->storage->writeFile($this->naviFolder, $this->draftNaviName, $draftNavigation, 'serialize');
|
||||
|
||||
return $draftNavigation;
|
||||
}
|
||||
|
||||
public function getBasicDraftNavigation($urlinfo, $language)
|
||||
{
|
||||
if(!$this->basicDraftNavigation)
|
||||
{
|
||||
$this->basicDraftNavigation = $this->createBasicDraftNavigation($urlinfo, $language);
|
||||
}
|
||||
return $this->basicDraftNavigation;
|
||||
}
|
||||
|
||||
# creates a fresh structure with published and non-published pages for the author
|
||||
public function createBasicDraftNavigation($urlinfo, $language)
|
||||
{
|
||||
$folder = new Folder();
|
||||
|
||||
# scan the content of the folder
|
||||
$draftContentTree = $folder->scanFolder($this->storage->getStorageInfo('contentFolder'), $draft = true);
|
||||
|
||||
# if there is content, then get the content details
|
||||
if(count($draftContentTree) > 0)
|
||||
{
|
||||
$draftNavigation = $folder->getFolderContentDetails($draftContentTree, $language, $urlinfo['baseurl'], $urlinfo['basepath']);
|
||||
|
||||
return $draftNavigation;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
# get the extended navigation with additional infos from the meta-files like title or hidden pages
|
||||
public function getExtendedNavigation($urlinfo, $language)
|
||||
{
|
||||
if(!$this->extendedNavigation)
|
||||
{
|
||||
# read the extended navi file
|
||||
$this->extendedNavigation = $this->storage->getYaml($this->naviFolder, $this->extendedNaviName);
|
||||
}
|
||||
|
||||
if(!$this->extendedNavigation)
|
||||
{
|
||||
$basicDraftNavigation = $this->getBasicDraftNavigation($urlinfo, $language);
|
||||
|
||||
$this->extendedNavigation = $this->createExtendedNavigation($basicDraftNavigation, $extended = NULL);
|
||||
|
||||
# cache it
|
||||
$this->storage->updateYaml($this->naviFolder, $this->extendedNaviName, $this->extendedNavigation);
|
||||
}
|
||||
|
||||
return $this->extendedNavigation;
|
||||
}
|
||||
|
||||
# reads all meta-files and creates an array with url => ['hide' => bool, 'navtitle' => 'bla']
|
||||
public function createExtendedNavigation($navigation, $extended = NULL)
|
||||
{
|
||||
if(!$extended)
|
||||
{
|
||||
$extended = [];
|
||||
}
|
||||
|
||||
$contentFolder = $this->storage->getStorageInfo('contentFolder');
|
||||
|
||||
foreach ($navigation as $key => $item)
|
||||
{
|
||||
# $filename = ($item->elementType == 'folder') ? DIRECTORY_SEPARATOR . 'index.yaml' : $item->pathWithoutType . '.yaml';
|
||||
$filename = $item->pathWithoutType . '.yaml';
|
||||
|
||||
if(file_exists($contentFolder . $filename))
|
||||
{
|
||||
# read file
|
||||
$meta = $this->storage->getYaml($contentFolder, $filename);
|
||||
|
||||
$extended[$item->urlRelWoF]['navtitle'] = isset($meta['meta']['navtitle']) ? $meta['meta']['navtitle'] : '';
|
||||
$extended[$item->urlRelWoF]['hide'] = isset($meta['meta']['hide']) ? $meta['meta']['hide'] : false;
|
||||
$extended[$item->urlRelWoF]['noindex'] = isset($meta['meta']['noindex']) ? $meta['meta']['noindex'] : false;
|
||||
$extended[$item->urlRelWoF]['path'] = $item->path;
|
||||
$extended[$item->urlRelWoF]['keyPath'] = $item->keyPath;
|
||||
}
|
||||
|
||||
if ($item->elementType == 'folder')
|
||||
{
|
||||
$extended = $this->createExtendedNavigation($item->folderContent, $extended);
|
||||
}
|
||||
}
|
||||
|
||||
return $extended;
|
||||
}
|
||||
|
||||
# merge a basic navigation (live or draft) with extended information from meta
|
||||
public function mergeNavigationWithExtended($navigation, $extended)
|
||||
{
|
||||
$mergedNavigation = [];
|
||||
|
||||
foreach($navigation as $key => $item)
|
||||
{
|
||||
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->noindex = (isset($extended[$item->urlRelWoF]['noindex']) && $extended[$item->urlRelWoF]['noindex'] === true) ? true : false;
|
||||
}
|
||||
|
||||
if($item->elementType == 'folder')
|
||||
{
|
||||
$item->folderContent = $this->mergeNavigationWithExtended($item->folderContent, $extended);
|
||||
}
|
||||
|
||||
$mergedNavigation[] = $item;
|
||||
}
|
||||
|
||||
return $mergedNavigation;
|
||||
}
|
||||
|
||||
public function getItemWithKeyPath($navigation, array $searchArray)
|
||||
{
|
||||
$item = false;
|
||||
|
||||
foreach($searchArray as $key => $itemKey)
|
||||
{
|
||||
$item = isset($navigation[$itemKey]) ? clone($navigation[$itemKey]) : false;
|
||||
|
||||
unset($searchArray[$key]);
|
||||
if(!empty($searchArray) && $item)
|
||||
{
|
||||
return $this->getItemWithKeyPath($item->folderContent, $searchArray);
|
||||
}
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
# reads the cached structure with published pages
|
||||
public function getLiveNavigation()
|
||||
{
|
||||
# get the cached navi
|
||||
$liveNavi = $this->storage->getFile($this->naviFolder, $this->liveNaviName, 'unserialize');
|
||||
|
||||
# if there is no cached structure
|
||||
if(!$liveNavi)
|
||||
{
|
||||
return $this->createNewLiveNavigation();
|
||||
}
|
||||
|
||||
return $liveNavi;
|
||||
}
|
||||
|
||||
# creates a fresh structure with published pages
|
||||
private function createNewLiveNavigation($urlinfo, $language)
|
||||
{
|
||||
$folder = new Folder();
|
||||
|
||||
# scan the content of the folder
|
||||
$draftNavi = $folder->scanFolder($this->storage->contentFolder, $draft = false);
|
||||
|
||||
# if there is content, then get the content details
|
||||
if($draftNavi && count($draftNavi) > 0)
|
||||
{
|
||||
# get the extended structure files with changes like navigation title or hidden pages
|
||||
$extended = $this->getExtendedNavi();
|
||||
|
||||
# create an array of object with the whole content of the folder and changes from extended file
|
||||
$liveNavi = $folder->getFolderContentDetails($liveNavi, $extended, $this->settings, $this->uri->getBaseUrl(), $this->uri->getBasePath());
|
||||
|
||||
# cache structure live
|
||||
$this->storage->writeFile($this->naviFolder, $this->liveNaviName, $liveNavi, 'serialize');
|
||||
|
||||
return $liveNavi;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,21 +4,23 @@ namespace Typemill\Models;
|
||||
|
||||
class Storage
|
||||
{
|
||||
public $error = false;
|
||||
public $error = false;
|
||||
|
||||
protected $basepath = false;
|
||||
protected $basepath = false;
|
||||
|
||||
protected $tmpFolder = false;
|
||||
protected $tmpFolder = false;
|
||||
|
||||
protected $originalFolder = false;
|
||||
protected $originalFolder = false;
|
||||
|
||||
protected $liveFolder = false;
|
||||
protected $liveFolder = false;
|
||||
|
||||
protected $thumbsFolder = false;
|
||||
protected $thumbsFolder = false;
|
||||
|
||||
protected $customFolder = false;
|
||||
protected $customFolder = false;
|
||||
|
||||
protected $fileFolder = false;
|
||||
protected $fileFolder = false;
|
||||
|
||||
protected $contentFolder = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -35,6 +37,8 @@ class Storage
|
||||
$this->customFolder = $this->basepath . 'media' . DIRECTORY_SEPARATOR . 'custom' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$this->fileFolder = $this->basepath . 'media' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$this->contentFolder = $this->basepath . 'content';
|
||||
}
|
||||
|
||||
public function getError()
|
||||
@@ -42,6 +46,15 @@ class Storage
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
public function getStorageInfo($item)
|
||||
{
|
||||
if(isset($this->$item))
|
||||
{
|
||||
return $this->$item;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkFolder($folder)
|
||||
{
|
||||
$folderpath = $this->basepath . $folder;
|
||||
@@ -87,7 +100,7 @@ class Storage
|
||||
return true;
|
||||
}
|
||||
|
||||
public function writeFile($folder, $filename, $data)
|
||||
public function writeFile($folder, $filename, $data, $method = NULL)
|
||||
{
|
||||
if(!$this->checkFolder($folder))
|
||||
{
|
||||
@@ -107,6 +120,12 @@ class Storage
|
||||
return false;
|
||||
}
|
||||
|
||||
# serialize, json_decode
|
||||
if($method && is_callable($method))
|
||||
{
|
||||
$data = $method($data);
|
||||
}
|
||||
|
||||
$writefile = fwrite($openfile, $data);
|
||||
if(!$writefile)
|
||||
{
|
||||
@@ -120,13 +139,19 @@ class Storage
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFile($folder, $filename)
|
||||
public function getFile($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;
|
||||
}
|
||||
|
||||
@@ -207,6 +232,8 @@ class Storage
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function createUniqueImageName($filename, $extension)
|
||||
{
|
||||
$defaultfilename = $filename;
|
||||
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Models;
|
||||
|
||||
class Yaml extends StorageWrapper
|
||||
{
|
||||
/**
|
||||
* Get the a yaml file.
|
||||
* @param string $fileName is the name of the Yaml Folder.
|
||||
* @param string $yamlFileName is the name of the Yaml File.
|
||||
*/
|
||||
public function getYaml($folderName, $yamlFileName)
|
||||
{
|
||||
die('Yaml class outdated. Use storage instead.');
|
||||
$yaml = $this->getFile($folderName, $yamlFileName);
|
||||
|
||||
if($yaml)
|
||||
{
|
||||
return \Symfony\Component\Yaml\Yaml::parse($yaml);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a yaml file.
|
||||
* @param string $fileName is the name of the Yaml Folder.
|
||||
* @param string $yamlFileName is the name of the Yaml File.
|
||||
* @param array $contentArray is the content as an array.
|
||||
*/
|
||||
public function updateYaml($folderName, $yamlFileName, $contentArray)
|
||||
{
|
||||
die('Yaml class outdated. Use storage instead.');
|
||||
$yaml = \Symfony\Component\Yaml\Yaml::dump($contentArray,6);
|
||||
if($this->writeFile($folderName, $yamlFileName, $yaml))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
22
system/typemill/author/content/blox-editor.twig
Normal file
22
system/typemill/author/content/blox-editor.twig
Normal file
@@ -0,0 +1,22 @@
|
||||
{% extends 'layouts/layoutContent.twig' %}
|
||||
{% block title %}{{ translate('Visual Editor') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1 class="text-3xl font-bold mb-4">{{ translate('Visual Editor') }} </h1>
|
||||
|
||||
<div id="veditor" v-cloak></div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
|
||||
<script src="{{ base_url() }}/system/typemill/author/js/highlight.min.js?v={{ settings.version }}"></script>
|
||||
<script src="{{ base_url() }}/system/typemill/author/js/vue-system.js?v={{ settings.version }}"></script>
|
||||
<script src="{{ base_url() }}/system/typemill/author/js/vue-translate.js?v={{ settings.version }}"></script>
|
||||
<script src="{{ base_url() }}/system/typemill/author/js/vue-shared.js?v={{ settings.version }}"></script>
|
||||
<script>
|
||||
app.mount('#veditor');
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
68
system/typemill/author/layouts/layoutContent.twig
Normal file
68
system/typemill/author/layouts/layoutContent.twig
Normal file
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<meta name="description" content="Edit your content with typemill"/>
|
||||
|
||||
<meta name="msapplication-TileColor" content="#F9F8F6" />
|
||||
<meta name="msapplication-TileImage" content="{{ base_url() }}/system/author/img/favicon-144.png" />
|
||||
<link rel="icon" type="image/png" href="{{ base_url() }}/system/author/img/favicon-16.png" sizes="16x16" />
|
||||
<link rel="icon" type="image/png" href="{{ base_url() }}/system/author/img/favicon-32.png" sizes="32x32" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="{{ base_url() }}/system/author/img/favicon-72.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="{{ base_url() }}/system/author/img/favicon-114.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="{{ base_url() }}/system/author/img/favicon-144.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ base_url() }}/system/author/img/favicon-180.png" />
|
||||
|
||||
<link rel="stylesheet" href="{{ base_url() }}/system/typemill/author/css/output.css?v={{ settings.version }}" />
|
||||
<link rel="stylesheet" href="{{ base_url() }}/system/typemill/author/css/custom.css?v={{ settings.version }}" />
|
||||
|
||||
{% block stylesheet %}{% endblock %}
|
||||
|
||||
{{ assets.renderCSS() }}
|
||||
|
||||
</head>
|
||||
<body class="bg-stone-100">
|
||||
|
||||
{% include 'partials/symbols.twig' %}
|
||||
|
||||
<header class="border-b-2 border-stone-200">
|
||||
{% include 'partials/mainNavi.twig' %}
|
||||
</header>
|
||||
|
||||
{% include 'partials/flash.twig' %}
|
||||
|
||||
<div class="max-w-6xl m-auto mt-7 flex justify-between" id="main" data-url="{{ base_url() }}">
|
||||
<aside class="w-1/4">
|
||||
{% include 'partials/contentNavi.twig' %}
|
||||
</aside>
|
||||
<article class="w-3/4 bg-stone-50 shadow-md p-8">
|
||||
{% block content %}{% endblock %}
|
||||
</article>
|
||||
</div>
|
||||
|
||||
{{ csrf() | raw }}
|
||||
|
||||
<script>
|
||||
|
||||
const data = {{ jsdata | json_encode() | raw }};
|
||||
const labels = {{ translations|json_encode() }};
|
||||
|
||||
</script>
|
||||
<script src="{{ base_url() }}/system/typemill/author/js/axios.min.js?v={{ settings.version }}"></script>
|
||||
<script>
|
||||
const tmaxios = axios.create();
|
||||
tmaxios.defaults.baseURL = "{{ base_url() }}";
|
||||
tmaxios.defaults.headers.common['X-Session-Auth'] = "true";
|
||||
</script>
|
||||
<script src="{{ base_url() }}/system/typemill/author/js/vue.js?v={{ settings.version }}"></script>
|
||||
<script src="{{ base_url() }}/system/typemill/author/js/vue-eventbus.js?v={{ settings.version }}"></script>
|
||||
|
||||
{% block javascript %}{% endblock %}
|
||||
|
||||
{{ assets.renderJS() }}
|
||||
|
||||
</body>
|
||||
</html>
|
13
system/typemill/author/partials/contentNavi.twig
Normal file
13
system/typemill/author/partials/contentNavi.twig
Normal file
@@ -0,0 +1,13 @@
|
||||
<nav class="max-w-6xl m-auto flex justify-between">
|
||||
<ul class="flex border-l-2 border-stone-200">
|
||||
<div id="contentNavigation" v-cloak></div>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{% block javascript %}
|
||||
|
||||
<script>
|
||||
app.mount('#contentNavigation');
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
114
system/typemill/author/partials/editorNavi.twig
Normal file
114
system/typemill/author/partials/editorNavi.twig
Normal file
@@ -0,0 +1,114 @@
|
||||
<nav id="sidebar-menu" class="sidebar-menu--content">
|
||||
<div id="data-navi" data-homepage='{{ homepage|json_encode() }}' data-editormode="{{settings.editor}}"></div>
|
||||
<div id="mobile-menu" class="menu-action">{{ __('Menu') }} <span class="button-arrow"></span></div>
|
||||
<div id="navi" class="content-navi" :value.sync="freeze" v-cloak>
|
||||
<div class="navi-list">
|
||||
<div class="navi-item folder">
|
||||
<div class="foldertoggle" @click="clearToggle"><svg class="icon icon-enlarge2"><use xlink:href="#icon-enlarge2"></use></svg></div>
|
||||
<div class="status" :class="homepage.status"></div>
|
||||
<a href="{{ base_url }}/tm/content/{{ settings.editor }}" :class="homepage.active"><span><span class="iconwrapper"><svg class="icon icon-home"><use xlink:href="#icon-home"></use></svg></span><span class="level-1">{{ __('Homepage') }}</span></a>
|
||||
</div>
|
||||
</div>
|
||||
<draggable class="navi-list" tag="ul"
|
||||
@start="onStart"
|
||||
@end="onEnd"
|
||||
:list="items"
|
||||
:move="checkMove"
|
||||
group="file"
|
||||
animation="150"
|
||||
:disabled="freeze">
|
||||
<navigation
|
||||
v-for="item in items"
|
||||
ref="draggit"
|
||||
:freeze="freeze"
|
||||
:name="item.name"
|
||||
:hide="item.hide"
|
||||
:active="item.active"
|
||||
:parent="item.activeParent"
|
||||
:level="item.keyPath"
|
||||
:root="root"
|
||||
:url="item.urlRelWoF"
|
||||
:id="item.keyPath"
|
||||
:key="item.keyPath"
|
||||
:elementtype="item.elementType"
|
||||
:contains="item.contains"
|
||||
:filetype="item.fileType"
|
||||
:status="item.status"
|
||||
:folder="item.folderContent"
|
||||
:collapse="collapse"
|
||||
></navigation>
|
||||
</draggable>
|
||||
<ul class="navi-list addBaseItem">
|
||||
<li class="navi-item file">
|
||||
<span class="iconwrapper">
|
||||
<svg class="icon icon-plus"><use xlink:href="#icon-plus"></use></svg>
|
||||
</span>
|
||||
<span class="addNaviItem">
|
||||
<a class="addNaviLink" href="#" @click.prevent="toggleForm">{{ __('add item') }}</a>
|
||||
</span>
|
||||
<transition name="fade">
|
||||
<div v-if="showForm" class="addNaviForm">
|
||||
<input v-model="newItem">
|
||||
<button class="b-left" @click="addFile('file')">{{ __('add file') }}</button><button class="b-right" @click="addFile('folder')">{{ __('add folder') }}</button>
|
||||
</div>
|
||||
</transition>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{% verbatim %}
|
||||
<template id="navigation-template">
|
||||
<li class="navi-item" :class="elementtype">
|
||||
<div v-if="folder" class="foldertoggle" @click="callToggle(name)"><svg v-if="isCollapsed(name)" class="icon icon-shrink2"><use xlink:href="#icon-shrink2"></use></svg><svg v-else class="icon icon-enlarge2"><use xlink:href="#icon-enlarge2"></use></svg></div>
|
||||
<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, hide)"><use :xlink:href="getIcon(elementtype, filetype, hide)"></use></svg></span><span :class="getLevel(level)">{{ name }}</span><span class="movewrapper"><svg class="icon icon-arrows-v"><use xlink:href="#icon-arrows-v"></use></svg></span></a>
|
||||
<draggable v-if="folder" v-show="!isCollapsed(name)" class="navi-list" tag="ul"
|
||||
@start="onStart"
|
||||
@end="onEnd"
|
||||
:list="folder"
|
||||
:move="checkMove"
|
||||
group="file"
|
||||
animation="150"
|
||||
:disabled="freeze">
|
||||
<navigation
|
||||
v-for="item in folder"
|
||||
v-if="contains == 'pages'"
|
||||
ref="draggit"
|
||||
:freeze="freeze"
|
||||
:name="item.name"
|
||||
:hide="item.hide"
|
||||
:active="item.active"
|
||||
:parent="item.activeParent"
|
||||
:level="item.keyPath"
|
||||
:url="item.urlRelWoF"
|
||||
:root="root"
|
||||
:id="item.keyPath"
|
||||
:key="item.keyPath"
|
||||
:filetype="item.fileType"
|
||||
:status="item.status"
|
||||
:elementtype="item.elementType"
|
||||
:contains="item.contains"
|
||||
:folder="item.folderContent"
|
||||
:collapse="collapse"
|
||||
></navigation>
|
||||
</draggable>
|
||||
<ul v-if="folder && contains == 'pages'" class="navi-list">
|
||||
<li class="navi-item file">
|
||||
<span class="iconwrapper">
|
||||
<svg class="icon icon-plus"><use xlink:href="#icon-plus"></use></svg>
|
||||
</span>
|
||||
<span :class="getLevel(level + '.0')" class="addNaviItem">
|
||||
<a class="addNaviLink" href="#" @click.prevent="toggleForm">{% endverbatim %}{{ __('add item') }}{% verbatim %}</a>
|
||||
</span>
|
||||
<transition name="fade">
|
||||
<div v-if="showForm" class="addNaviForm">
|
||||
<input v-model="newItem">
|
||||
<button class="b-left" @click="addFile('file')">{% endverbatim %}{{ __('add file') }}{% verbatim %}</button><button class="b-right" @click="addFile('folder')">{% endverbatim %}{{ __('add folder') }}{% verbatim %}</button>
|
||||
</div>
|
||||
</transition>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
{% endverbatim %}
|
@@ -6,6 +6,7 @@ use Typemill\Middleware\WebRedirectIfUnauthenticated;
|
||||
use Typemill\Middleware\WebAuthorization;
|
||||
use Typemill\Controllers\ControllerWebAuth;
|
||||
use Typemill\Controllers\ControllerWebSystem;
|
||||
use Typemill\Controllers\ControllerWebAuthor;
|
||||
use Typemill\Controllers\ControllerWebFrontend;
|
||||
#use Slim\Views\TwigMiddleware;
|
||||
|
||||
@@ -20,6 +21,7 @@ $app->group('/tm', function (RouteCollectorProxy $group) {
|
||||
# author and editor area, requires authentication
|
||||
$app->group('/tm', function (RouteCollectorProxy $group) use ($routeParser,$acl) {
|
||||
|
||||
# Admin Area
|
||||
$group->get('/logout', ControllerWebAuth::class . ':logout')->setName('auth.logout');
|
||||
$group->get('/system', ControllerWebSystem::class . ':showSettings')->setName('settings.show')->add(new WebAuthorization($routeParser, $acl, 'system', 'show')); # admin;
|
||||
$group->get('/license', ControllerWebSystem::class . ':showLicense')->setName('license.show')->add(new WebAuthorization($routeParser, $acl, 'system', 'show')); # admin;
|
||||
@@ -30,8 +32,8 @@ $app->group('/tm', function (RouteCollectorProxy $group) use ($routeParser,$acl)
|
||||
$group->get('/user/new', ControllerWebSystem::class . ':newUser')->setName('user.new')->add(new WebAuthorization($routeParser, $acl, 'user', 'create')); # admin;
|
||||
$group->get('/user/{username}', ControllerWebSystem::class . ':showUser')->setName('user.show')->add(new WebAuthorization($routeParser, $acl, 'user', 'show')); # admin;;
|
||||
|
||||
# REFACTOR
|
||||
$group->get('/content/visual[/{params:.*}]', ControllerAuthorEditor::class . ':showBlox')->setName('content.visual');
|
||||
# Author Area
|
||||
$group->get('/content/visual[/{route:.*}]', ControllerWebAuthor::class . ':showBlox')->setName('content.visual')->add(new WebAuthorization($routeParser, $acl, 'mycontent', 'view'));
|
||||
|
||||
})->add(new WebRedirectIfUnauthenticated($routeParser));
|
||||
|
||||
|
Reference in New Issue
Block a user