Compare commits
No commits in common. "beta" and "b2.4.0" have entirely different histories.
142 changed files with 4883 additions and 37499 deletions
14
.babelrc
14
.babelrc
|
@ -1,13 +1 @@
|
||||||
{
|
{ "presets": ["env"] }
|
||||||
"presets": [],
|
|
||||||
"plugins": [
|
|
||||||
[
|
|
||||||
"prismjs",
|
|
||||||
{
|
|
||||||
"languages": ["html", "markdown", "markup"],
|
|
||||||
"theme": "okaidia",
|
|
||||||
"css": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
"no-unsafe-finally": 2,
|
"no-unsafe-finally": 2,
|
||||||
"no-unsafe-negation": 2,
|
"no-unsafe-negation": 2,
|
||||||
"no-unused-labels": 2,
|
"no-unused-labels": 2,
|
||||||
"no-unused-vars": 1,
|
"no-unused-vars": 2,
|
||||||
"no-useless-escape": 1,
|
"no-useless-escape": 1,
|
||||||
"require-yield": 2,
|
"require-yield": 2,
|
||||||
"use-isnan": 2,
|
"use-isnan": 2,
|
||||||
|
|
31
.gitignore
vendored
31
.gitignore
vendored
|
@ -1,6 +1,5 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
src/node_modules/
|
src/node_modules/
|
||||||
.parcel-cache/
|
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
.cache/
|
.cache/
|
||||||
.nova/
|
.nova/
|
||||||
|
@ -12,21 +11,11 @@ public/*
|
||||||
public/assets/*
|
public/assets/*
|
||||||
!public/assets/css
|
!public/assets/css
|
||||||
public/assets/css/*
|
public/assets/css/*
|
||||||
!public/assets/css/dash
|
!public/assets/css/dash.css
|
||||||
!public/assets/scripts
|
!public/assets/scripts
|
||||||
public/assets/scripts/*
|
public/assets/scripts/*
|
||||||
<<<<<<< HEAD
|
!public/assets/scripts/dash.min.js
|
||||||
!public/assets/scripts/Start.js
|
|
||||||
/public/assets/images/global/rikc-logo.svg
|
|
||||||
|
|
||||||
|
|
||||||
=======
|
|
||||||
!public/assets/scripts/dash.js
|
|
||||||
<<<<<<< HEAD
|
|
||||||
>>>>>>> develop
|
|
||||||
=======
|
|
||||||
!public/assets/scripts/dash.js.map
|
|
||||||
>>>>>>> develop
|
|
||||||
!public/assets/images
|
!public/assets/images
|
||||||
public/assets/images/*
|
public/assets/images/*
|
||||||
!public/assets/images/global/
|
!public/assets/images/global/
|
||||||
|
@ -52,7 +41,15 @@ config/tags.json
|
||||||
config.codekit3
|
config.codekit3
|
||||||
/config/backups
|
/config/backups
|
||||||
|
|
||||||
src/com/*
|
/src/com
|
||||||
src/styles/*
|
/src/style
|
||||||
|
/src/node_modules
|
||||||
src/com/ui/TextEditor.js
|
/src/com/Base.js
|
||||||
|
/src/com/controllers/NavIndex.js
|
||||||
|
/src/com/controllers/PageEditor.js
|
||||||
|
/src/com/controllers/SettingsIndex.js
|
||||||
|
/src/libraries/FipamoAPI.js
|
||||||
|
/src/package-lock.json
|
||||||
|
/src/package.json
|
||||||
|
/public/assets/images/global/rikc-logo.svg
|
||||||
|
/src/styles/
|
|
@ -1,74 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
$config = new PhpCsFixer\Config();
|
|
||||||
return $config
|
|
||||||
->setRiskyAllowed(true)
|
|
||||||
->setRules([
|
|
||||||
'@PSR12' => true,
|
|
||||||
'array_indentation' => true,
|
|
||||||
'array_syntax' => [
|
|
||||||
'syntax' => 'short',
|
|
||||||
],
|
|
||||||
'combine_consecutive_unsets' => true,
|
|
||||||
'method_chaining_indentation' => true,
|
|
||||||
'class_attributes_separation' => [
|
|
||||||
'elements' => [
|
|
||||||
'const' => 'none',
|
|
||||||
'method' => 'one',
|
|
||||||
'property' => 'none',
|
|
||||||
'trait_import' => 'none',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'multiline_whitespace_before_semicolons' => [
|
|
||||||
'strategy' => 'no_multi_line',
|
|
||||||
],
|
|
||||||
'single_quote' => false,
|
|
||||||
|
|
||||||
'binary_operator_spaces' => [
|
|
||||||
'default' => 'single_space',
|
|
||||||
'operators' => [
|
|
||||||
'=' => 'align_single_space_minimal',
|
|
||||||
'=>' => 'align_single_space_minimal',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'braces' => [
|
|
||||||
'allow_single_line_closure' => true,
|
|
||||||
],
|
|
||||||
'concat_space' => [
|
|
||||||
'spacing' => 'one',
|
|
||||||
],
|
|
||||||
'declare_equal_normalize' => true,
|
|
||||||
'function_typehint_space' => true,
|
|
||||||
'single_line_comment_style' => [
|
|
||||||
'comment_types' => [
|
|
||||||
'hash',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'include' => true,
|
|
||||||
'lowercase_cast' => true,
|
|
||||||
'no_extra_blank_lines' => [
|
|
||||||
'tokens' => [
|
|
||||||
'curly_brace_block',
|
|
||||||
'extra',
|
|
||||||
'parenthesis_brace_block',
|
|
||||||
'throw',
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'no_multiline_whitespace_around_double_arrow' => true,
|
|
||||||
'no_spaces_around_offset' => true,
|
|
||||||
'no_unused_imports' => true,
|
|
||||||
'no_whitespace_before_comma_in_array' => true,
|
|
||||||
'no_whitespace_in_blank_line' => true,
|
|
||||||
'object_operator_without_whitespace' => true,
|
|
||||||
'single_blank_line_before_namespace' => true,
|
|
||||||
'ternary_operator_spaces' => true,
|
|
||||||
'trim_array_spaces' => true,
|
|
||||||
'unary_operator_spaces' => true,
|
|
||||||
'whitespace_after_comma_in_array' => true,
|
|
||||||
'single_line_after_imports' => true,
|
|
||||||
'ordered_imports' => [
|
|
||||||
'sort_algorithm' => 'none',
|
|
||||||
],
|
|
||||||
//Other rules here...
|
|
||||||
])
|
|
||||||
->setLineEnding("\n");
|
|
|
@ -1,7 +0,0 @@
|
||||||
.babelrc
|
|
||||||
README.md
|
|
||||||
*.twig
|
|
||||||
*.sass
|
|
||||||
*.json
|
|
||||||
*.php
|
|
||||||
*.md
|
|
36
.prettierrc
36
.prettierrc
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": ".prettierrc",
|
|
||||||
"options": { "parser": "json" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": "*.scss",
|
|
||||||
"options": {
|
|
||||||
"tabWidth": 4,
|
|
||||||
"semi": false,
|
|
||||||
"singleQuote": true,
|
|
||||||
"printWidth": 90
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": "*.js",
|
|
||||||
"options": {
|
|
||||||
"arrowParens": "avoid",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"htmlWhitespaceSensitivity": "css",
|
|
||||||
"insertPragma": false,
|
|
||||||
"bracketSameLine": false,
|
|
||||||
"jsxSingleQuote": true,
|
|
||||||
"proseWrap": "preserve",
|
|
||||||
"requirePragma": false,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "none",
|
|
||||||
"useTabs": true,
|
|
||||||
"tabWidth": 4,
|
|
||||||
"printWidth": 90
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"extends": ["stylelint-config-standard"]
|
|
||||||
}
|
|
|
@ -1,9 +1,13 @@
|
||||||
|
![This is Fipamo](https://playvicio.us/base-assets/images/fipamo-brand.png)
|
||||||
|
|
||||||
# Fipamo means to save
|
# Fipamo means to save
|
||||||
|
|
||||||
The Fipamo project was born from a need for a simple, easy to use no data blog platform that doesn't require much effort to set up and maintain. Fipamo uses Markdown to handle posts and renders them to flat html so you can serve them from anywhere. No complicated set ups. No long list of dependencies. Just set up and go.
|
The Fipamo project was born from a need for a simple, easy to use no data blog platform that doesn't require much effort to set up and maintain. Fipamo uses Markdown to handle posts and renders them to flat html so you can serve them from anywhere. No complicated set ups. No long list of dependencies. Just write and publish.
|
||||||
|
|
||||||
Because nobody has time for all that.
|
Because nobody has time for all that.
|
||||||
|
|
||||||
## Check the (WIP) Docs to get you started. <br>
|
## Check the (WIP) Docs to get you started. <br>
|
||||||
|
|
||||||
[Getting Started](https://koodu.ubiqueros.com/are0h/Fipamo/wiki/00---Start) <br>
|
[Getting Started](https://code.playvicio.us/Are0h/Fipamo/wiki/00---Start) <br>
|
||||||
|
[Install](https://code.playvicio.us/Are0h/Fipamo/wiki/01---Install) <br>
|
||||||
|
[Using Fipamo](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage) <br>
|
||||||
|
|
47
brain/App.inc.php
Normal file
47
brain/App.inc.php
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
use Slim\Factory\AppFactory;
|
||||||
|
use Slim\Views\Twig;
|
||||||
|
use Slim\Views\TwigMiddleware;
|
||||||
|
|
||||||
|
include "../brain/controller/RouteControl.inc.php";
|
||||||
|
include "../brain/data/Settings.inc.php";
|
||||||
|
include "../brain/data/Session.inc.php";
|
||||||
|
include "../brain/data/Member.inc.php";
|
||||||
|
include "../brain/data/Auth.inc.php";
|
||||||
|
include "../brain/data/Render.inc.php";
|
||||||
|
include "../brain/data/Themes.inc.php";
|
||||||
|
include "../brain/utility/StringTools.inc.php";
|
||||||
|
include "../brain/utility/FileUploader.inc.php";
|
||||||
|
include "../brain/utility/DocTools.inc.php";
|
||||||
|
include "../brain/utility/Sorting.inc.php";
|
||||||
|
include "../brain/utility/Setup.inc.php";
|
||||||
|
include "../brain/utility/Maintenance.inc.php";
|
||||||
|
include "../brain/utility/Mailer.inc.php";
|
||||||
|
include "../brain/utility/HandleCors.inc.php";
|
||||||
|
|
||||||
|
class App
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// set up cors
|
||||||
|
new HandleCors();
|
||||||
|
$app = AppFactory::create();
|
||||||
|
$twig = Twig::create("../brain/views/");
|
||||||
|
$app->add(TwigMiddleware::create($app, $twig));
|
||||||
|
//set up routing
|
||||||
|
$app->get(
|
||||||
|
"/[{first}[/{second}[/{third}[/{fourth}[/{fifth}]]]]]",
|
||||||
|
"\RouteControl:get"
|
||||||
|
);
|
||||||
|
$app->post(
|
||||||
|
"/[{first}[/{second}[/{third}[/{fourth}]]]]",
|
||||||
|
"\RouteControl:post"
|
||||||
|
);
|
||||||
|
//start the app
|
||||||
|
|
||||||
|
$app->run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
spl_autoload_register(function ($className) {
|
|
||||||
$file = dirname(__DIR__) . '\\' . $className . '.php';
|
|
||||||
$file = str_replace('\\', DIRECTORY_SEPARATOR, $file);
|
|
||||||
//echo $file;
|
|
||||||
if (file_exists($file)) {
|
|
||||||
include $file;
|
|
||||||
}
|
|
||||||
});
|
|
74
brain/api/v1/AuthAPI.inc.php
Normal file
74
brain/api/v1/AuthAPI.inc.php
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class AuthAPI
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function status()
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
//internal check for admin action
|
||||||
|
if (Auth::status()) {
|
||||||
|
$result = [
|
||||||
|
"message" => "Authorized",
|
||||||
|
"type" => "apiUseAuthorized",
|
||||||
|
"token" => Session::get("token"),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Not Authorized",
|
||||||
|
"type" => "apiUseNotAuthorized",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function login($body)
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
switch (Auth::login($body)) {
|
||||||
|
case "no_name":
|
||||||
|
$result = [
|
||||||
|
"message" => "Need to see some id, champ",
|
||||||
|
"type" => "requestLame",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case "bad_pass":
|
||||||
|
$result = [
|
||||||
|
"message" => "Check your password, sport",
|
||||||
|
"type" => "requestLame",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = [
|
||||||
|
"message" => "Welcome back",
|
||||||
|
"type" => "requestGood",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function logout($body)
|
||||||
|
{
|
||||||
|
Auth::logout($body);
|
||||||
|
$result = [
|
||||||
|
"message" => "Till next time, g.",
|
||||||
|
"type" => "TASK_LOGOUT",
|
||||||
|
];
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
public static function requestSecret($body)
|
||||||
|
{
|
||||||
|
$result = Auth::findSecret($body);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
public static function resetPassword($body)
|
||||||
|
{
|
||||||
|
$result = Auth::makeNewPassword($body);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,81 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\api\v1;
|
|
||||||
|
|
||||||
use brain\data\Auth;
|
|
||||||
use brain\data\Session;
|
|
||||||
|
|
||||||
class AuthAPI
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function status()
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
//internal check for admin action
|
|
||||||
if (Auth::status()) {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Authorized',
|
|
||||||
'type' => 'apiUseAuthorized',
|
|
||||||
'token' => Session::get('token'),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Not Authorized',
|
|
||||||
'type' => 'apiUseNotAuthorized',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function login($body)
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
switch (Auth::login($body)) {
|
|
||||||
case 'no_name':
|
|
||||||
$result = [
|
|
||||||
'message' => 'Need to see some id, champ',
|
|
||||||
'type' => 'requestLame',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'bad_pass':
|
|
||||||
$result = [
|
|
||||||
'message' => 'Check your password, sport',
|
|
||||||
'type' => 'requestLame',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$result = [
|
|
||||||
'message' => 'Welcome back',
|
|
||||||
'type' => 'requestGood',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function logout($body)
|
|
||||||
{
|
|
||||||
Auth::logout($body);
|
|
||||||
$result = [
|
|
||||||
'message' => 'Till next time, g.',
|
|
||||||
'type' => 'TASK_LOGOUT',
|
|
||||||
];
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function requestSecret($body)
|
|
||||||
{
|
|
||||||
$result = Auth::findSecret($body);
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function resetPassword($body)
|
|
||||||
{
|
|
||||||
$result = Auth::makeNewPassword($body);
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\api\v1;
|
|
||||||
|
|
||||||
use brain\utility\FileUploader;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use brain\data\Member;
|
|
||||||
|
|
||||||
class FilesAPI
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function uploadFiles($request, $type = null)
|
|
||||||
{
|
|
||||||
$upload = $request->getUploadedFiles(); //grab uploaded files
|
|
||||||
$options = $request->getParsedBody();
|
|
||||||
$file = $upload['upload_files'][0]; //front end sends one by one for progress tracking, so grab first
|
|
||||||
$type = $file->getClientMediaType();
|
|
||||||
$filesPath = '';
|
|
||||||
$path = date('Y') . '/' . date('m');
|
|
||||||
$response = [];
|
|
||||||
|
|
||||||
switch ($type) {
|
|
||||||
case 'image/jpeg':
|
|
||||||
case 'image/png':
|
|
||||||
case 'image/gif':
|
|
||||||
case 'image/svg':
|
|
||||||
if (isset($options["source"])) {
|
|
||||||
if ($options["source"] == "avatar-upload") {
|
|
||||||
$filesPath = '/assets/images/user/' . $path . '/';
|
|
||||||
Member::updateData(
|
|
||||||
'avi',
|
|
||||||
$filesPath . $file->getClientFileName()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$filesPath = '/assets/images/user/' . $path . '/';
|
|
||||||
Settings::updateGlobalData(
|
|
||||||
'background',
|
|
||||||
$filesPath . '/' . $file->getClientFileName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$filesPath = '/assets/images/blog/' . $path . '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'video/mp4':
|
|
||||||
$filesPath = '/assets/video/blog/' . $path . '/';
|
|
||||||
break;
|
|
||||||
case 'audio/mpeg':
|
|
||||||
$filesPath = '/assets/sound/blog/' . $path . '/';
|
|
||||||
break;
|
|
||||||
case 'application/pdf':
|
|
||||||
case 'text/plain':
|
|
||||||
case 'text/rtf':
|
|
||||||
$filesPath = '/assets/docs/blog/' . $path . '/';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileUploader::uploadFile('../public' . $filesPath, $file);
|
|
||||||
|
|
||||||
$response = [
|
|
||||||
'message' => "File Uploaded. Great!",
|
|
||||||
"filePath" => $filesPath . urlencode($file->getClientFileName()),
|
|
||||||
"fileName" => urlencode($file->getClientFileName()),
|
|
||||||
'type' => $type,
|
|
||||||
];
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
}
|
|
76
brain/api/v1/ImagesAPI.inc.php
Normal file
76
brain/api/v1/ImagesAPI.inc.php
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class ImagesAPI
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function uploadImage($request, $type = null)
|
||||||
|
{
|
||||||
|
$file = $request->getUploadedFiles();
|
||||||
|
$uploadPath = "";
|
||||||
|
$path = date("Y") . "/" . date("m");
|
||||||
|
$response = [];
|
||||||
|
switch ($type) {
|
||||||
|
case "avatar":
|
||||||
|
$image = $file["avatar_upload"];
|
||||||
|
$uploadPath = "../public/assets/images/user/" . $path;
|
||||||
|
break;
|
||||||
|
case "background":
|
||||||
|
$image = $file["background_upload"];
|
||||||
|
$uploadPath = "../public/assets/images/user/" . $path;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$image = $file["post_image"];
|
||||||
|
$path = date("Y") . "/" . date("m");
|
||||||
|
$uploadPath = "../public/assets/images/blog/" . $path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = FileUploader::uploadFile($uploadPath, $image);
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case "avatar":
|
||||||
|
$response = [
|
||||||
|
"message" => "Avatar Added. You look great!",
|
||||||
|
"type" => "avatarUploaded",
|
||||||
|
"url" =>
|
||||||
|
"/assets/images/user/" . $path . "/" . $image->getClientFileName(),
|
||||||
|
];
|
||||||
|
|
||||||
|
//update member data
|
||||||
|
Member::updateData(
|
||||||
|
"avi",
|
||||||
|
"/assets/images/user/" . $path . "/" . $image->getClientFileName()
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "background":
|
||||||
|
$response = [
|
||||||
|
"message" => "Background plugged in. That's nice!",
|
||||||
|
"type" => "siteBackgroundUploaded",
|
||||||
|
"url" =>
|
||||||
|
"/assets/images/user/" . $path . "/" . $image->getClientFileName(),
|
||||||
|
];
|
||||||
|
|
||||||
|
//update settings file
|
||||||
|
Settings::updateGlobalData(
|
||||||
|
"background",
|
||||||
|
"/assets/images/user/" . $path . "/" . $image->getClientFileName()
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$response = [
|
||||||
|
"message" => "Image Added. Very slick",
|
||||||
|
"type" => "postImageAdded",
|
||||||
|
"url" =>
|
||||||
|
"/assets/images/blog/" . $path . "/" . $image->getClientFileName(),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,79 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\api\v1;
|
|
||||||
|
|
||||||
use brain\data\Member;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use brain\utility\FileUploader;
|
|
||||||
|
|
||||||
class ImagesAPI
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function uploadImage($request, $type = null)
|
|
||||||
{
|
|
||||||
$file = $request->getUploadedFiles();
|
|
||||||
$uploadPath = '';
|
|
||||||
$path = date('Y') . '/' . date('m');
|
|
||||||
$response = [];
|
|
||||||
switch ($type) {
|
|
||||||
case 'avatar':
|
|
||||||
$image = $file['avatar_upload'];
|
|
||||||
$uploadPath = '../public/assets/images/user/' . $path;
|
|
||||||
break;
|
|
||||||
case 'background':
|
|
||||||
$image = $file['background_upload'];
|
|
||||||
$uploadPath = '../public/assets/images/user/' . $path;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$image = $file['post_image'];
|
|
||||||
$path = date('Y') . '/' . date('m');
|
|
||||||
$uploadPath = '../public/assets/images/blog/' . $path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = FileUploader::uploadFile($uploadPath, $image);
|
|
||||||
|
|
||||||
switch ($type) {
|
|
||||||
case 'avatar':
|
|
||||||
$response = [
|
|
||||||
'message' => 'Avatar Added. You look great!',
|
|
||||||
'type' => 'avatarUploaded',
|
|
||||||
'url' => '/assets/images/user/' . $path . '/' . $image->getClientFileName(),
|
|
||||||
];
|
|
||||||
|
|
||||||
//update member data
|
|
||||||
Member::updateData(
|
|
||||||
'avi',
|
|
||||||
'/assets/images/user/' . $path . '/' . $image->getClientFileName()
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'background':
|
|
||||||
$response = [
|
|
||||||
'message' => "Background plugged in. That's nice!",
|
|
||||||
'type' => 'siteBackgroundUploaded',
|
|
||||||
'url' => '/assets/images/user/' . $path . '/' . $image->getClientFileName(),
|
|
||||||
];
|
|
||||||
|
|
||||||
//update settings file
|
|
||||||
Settings::updateGlobalData(
|
|
||||||
'background',
|
|
||||||
'/assets/images/user/' . $path . '/' . $image->getClientFileName()
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$response = [
|
|
||||||
'message' => 'Image Added. Very slick',
|
|
||||||
'type' => 'postImageAdded',
|
|
||||||
'url' => '/assets/images/blog/' . $path . '/' . $image->getClientFileName(),
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
}
|
|
30
brain/api/v1/InitAPI.inc.php
Normal file
30
brain/api/v1/InitAPI.inc.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class InitAPI
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function handleInitTasks($task, $request)
|
||||||
|
{
|
||||||
|
//check if a site config already exists. if it does, deny set up request
|
||||||
|
//restore to previous version of site while a config exists is only accessible
|
||||||
|
//through settings.
|
||||||
|
|
||||||
|
if (Setup::status()) {
|
||||||
|
$result = ["type" => "blogInitFail", "message" => "Site already set up"];
|
||||||
|
} else {
|
||||||
|
switch ($task) {
|
||||||
|
case "init":
|
||||||
|
$result = Setup::init($request);
|
||||||
|
break;
|
||||||
|
case "restore":
|
||||||
|
$result = Setup::restore($request);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\api\v1;
|
|
||||||
|
|
||||||
use brain\utility\Setup;
|
|
||||||
|
|
||||||
class InitAPI
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function handleInitTasks($task, $request)
|
|
||||||
{
|
|
||||||
//check if a site config already exists. if it does, deny set up request
|
|
||||||
//restore to previous version of site while a config exists is only accessible
|
|
||||||
//through settings.
|
|
||||||
|
|
||||||
if (Setup::status()) {
|
|
||||||
$result = ['type' => 'blogInitFail', 'message' => 'Site already set up'];
|
|
||||||
} else {
|
|
||||||
switch ($task) {
|
|
||||||
case 'init':
|
|
||||||
$result = Setup::init($request);
|
|
||||||
break;
|
|
||||||
case 'restore':
|
|
||||||
$result = Setup::restore($request);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
26
brain/api/v1/MailerAPI.inc.php
Normal file
26
brain/api/v1/MailerAPI.inc.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class MailerAPI
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function handleMail($request, $body, $response)
|
||||||
|
{
|
||||||
|
//if testing, verify session is active
|
||||||
|
if ($body["mail_task"] == "TESTING") {
|
||||||
|
if (Session::active()) {
|
||||||
|
$result = Mailer::sendmail($body);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "You need to be logged in for this, champ.",
|
||||||
|
"type" => "MAILER_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\api\v1;
|
|
||||||
|
|
||||||
use brain\data\Session;
|
|
||||||
use brain\utility\Mailer;
|
|
||||||
|
|
||||||
class MailerAPI
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function handleMail($request, $body, $response)
|
|
||||||
{
|
|
||||||
// if testing, verify session is active
|
|
||||||
// add clean method for sending programmtic emails
|
|
||||||
if ($body['mail_task'] == 'TESTING') {
|
|
||||||
if (Session::active()) {
|
|
||||||
$result = Mailer::sendmail($body);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'You need to be logged in for this, champ.',
|
|
||||||
'type' => 'MAILER_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
174
brain/api/v1/PagesAPI.inc.php
Normal file
174
brain/api/v1/PagesAPI.inc.php
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
<?php
|
||||||
|
use function _\filter;
|
||||||
|
use Mni\FrontYAML\Parser;
|
||||||
|
|
||||||
|
class PagesAPI
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getPageContent($request, $args)
|
||||||
|
{
|
||||||
|
$task = $args["fourth"];
|
||||||
|
$pages = (new Book("../content/pages"))->getContents();
|
||||||
|
$content = [];
|
||||||
|
foreach ($pages as $page) {
|
||||||
|
$entry = [
|
||||||
|
"id" => $page["id"],
|
||||||
|
"uuid" => $page["uuid"],
|
||||||
|
"title" => $page["title"],
|
||||||
|
"feature" => $page["feature"],
|
||||||
|
"path" => $page["path"],
|
||||||
|
"layout" => $page["layout"],
|
||||||
|
"tags" => $page["tags"],
|
||||||
|
"author" => $page["author"],
|
||||||
|
"created" => $page["created"],
|
||||||
|
"updated" => $page["updated"],
|
||||||
|
"deleted" => $page["deleted"],
|
||||||
|
"menu" => $page["menu"],
|
||||||
|
"featured" => $page["featured"],
|
||||||
|
"published" => $page["published"],
|
||||||
|
"slug" => $page["slug"],
|
||||||
|
"content" => StringTools::sanitizeContent($page["content"]),
|
||||||
|
];
|
||||||
|
|
||||||
|
array_push($content, $entry);
|
||||||
|
}
|
||||||
|
switch ($task) {
|
||||||
|
case "published":
|
||||||
|
$published = filter($content, function ($item) {
|
||||||
|
return $item["published"] == true && $item["deleted"] == false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$result = ["pages" => $published, "totalItems" => count($published)];
|
||||||
|
break;
|
||||||
|
case "featured":
|
||||||
|
$featured = filter($content, function ($item) {
|
||||||
|
return $item["featured"] == true && $item["deleted"] == false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
"pages" => $featured,
|
||||||
|
"totalItems" => count($featured),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case "menu":
|
||||||
|
$menu = filter($content, function ($item) {
|
||||||
|
return $item["menu"] == true && $item["deleted"] == false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$result = ["pages" => $menu, "totalItems" => count($menu)];
|
||||||
|
break;
|
||||||
|
case "single":
|
||||||
|
$uuid = $args["fifth"];
|
||||||
|
$page = (new Book("../content/pages"))->findPageById($uuid);
|
||||||
|
|
||||||
|
$entry = [
|
||||||
|
"id" => $page["id"],
|
||||||
|
"uuid" => $page["uuid"],
|
||||||
|
"title" => $page["title"],
|
||||||
|
"feature" => $page["feature"],
|
||||||
|
"path" => $page["path"],
|
||||||
|
"layout" => $page["layout"],
|
||||||
|
"tags" => $page["tags"],
|
||||||
|
"author" => $page["author"],
|
||||||
|
"created" => $page["created"],
|
||||||
|
"updated" => $page["updated"],
|
||||||
|
"deleted" => $page["deleted"],
|
||||||
|
"menu" => $page["menu"],
|
||||||
|
"featured" => $page["featured"],
|
||||||
|
"published" => $page["published"],
|
||||||
|
"slug" => $page["slug"],
|
||||||
|
"content" => StringTools::sanitizeContent($page["content"]),
|
||||||
|
];
|
||||||
|
$result = $entry;
|
||||||
|
break;
|
||||||
|
case "tags":
|
||||||
|
$result = Settings::getTags();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = [
|
||||||
|
"message" => "Hm, no task. That's unfortunate",
|
||||||
|
"type" => "TASK_NONE",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function handlePageTask($request, $args)
|
||||||
|
{
|
||||||
|
$task = $args["fourth"];
|
||||||
|
switch ($task) {
|
||||||
|
case "delete":
|
||||||
|
case "create":
|
||||||
|
case "write":
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
$passed = true;
|
||||||
|
if (!isset($body["form_token"])) {
|
||||||
|
$result = [
|
||||||
|
"message" => "No form token. Not good, sport.",
|
||||||
|
"type" => "TASK_FORM_AUTH",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
if ($body["form_token"] == Session::get("form_token")) {
|
||||||
|
//TODO: Verify form fields
|
||||||
|
$keys = [
|
||||||
|
"id",
|
||||||
|
"uuid",
|
||||||
|
"layout",
|
||||||
|
"current_title",
|
||||||
|
"content",
|
||||||
|
"title",
|
||||||
|
"created",
|
||||||
|
"slug",
|
||||||
|
"tags",
|
||||||
|
"menu",
|
||||||
|
"featured",
|
||||||
|
"published",
|
||||||
|
"form_token",
|
||||||
|
"feature_image",
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($body as $key => $item) {
|
||||||
|
if (!in_array($key, $keys)) {
|
||||||
|
//found unnecessary key, so reject submission
|
||||||
|
$passed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($passed) {
|
||||||
|
$result = (new Book("../content/pages"))->editPage(
|
||||||
|
$task,
|
||||||
|
$request
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" =>
|
||||||
|
"Unneccessary key found. Post not authorized, slick.",
|
||||||
|
"type" => "TASK_FORM_AUTH",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Form token, auth failed. Uh oh.",
|
||||||
|
"type" => "TASK_FORM_AUTH",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "add-entry-image":
|
||||||
|
$result = ImagesAPI::uploadImage($request);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = [
|
||||||
|
"message" => "Hm, no task. That's unfortunate",
|
||||||
|
"type" => "TASK_NONE",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,179 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\api\v1;
|
|
||||||
|
|
||||||
use brain\data\Book;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use brain\data\Session;
|
|
||||||
use brain\utility\StringTools;
|
|
||||||
|
|
||||||
use function _\filter;
|
|
||||||
|
|
||||||
class PagesAPI
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getPageContent($request, $args)
|
|
||||||
{
|
|
||||||
$task = $args['fourth'];
|
|
||||||
$pages = (new Book('../content/pages'))->getContents();
|
|
||||||
$content = [];
|
|
||||||
foreach ($pages as $page) {
|
|
||||||
$entry = [
|
|
||||||
'id' => $page['id'],
|
|
||||||
'uuid' => $page['uuid'],
|
|
||||||
'title' => $page['title'],
|
|
||||||
'feature' => $page['feature'],
|
|
||||||
'path' => $page['path'],
|
|
||||||
'layout' => $page['layout'],
|
|
||||||
'tags' => $page['tags'],
|
|
||||||
'author' => $page['author'],
|
|
||||||
'created' => $page['created'],
|
|
||||||
'updated' => $page['updated'],
|
|
||||||
'deleted' => $page['deleted'],
|
|
||||||
'menu' => $page['menu'],
|
|
||||||
'featured' => $page['featured'],
|
|
||||||
'published' => $page['published'],
|
|
||||||
'slug' => $page['slug'],
|
|
||||||
'content' => StringTools::sanitizeContent($page['content']),
|
|
||||||
];
|
|
||||||
|
|
||||||
array_push($content, $entry);
|
|
||||||
}
|
|
||||||
switch ($task) {
|
|
||||||
case 'published':
|
|
||||||
$published = filter($content, function ($item) {
|
|
||||||
return $item['published'] == true && $item['deleted'] == false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$result = ['pages' => $published, 'totalItems' => count($published)];
|
|
||||||
break;
|
|
||||||
case 'featured':
|
|
||||||
$featured = filter($content, function ($item) {
|
|
||||||
return $item['featured'] == true && $item['deleted'] == false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$result = [
|
|
||||||
'pages' => $featured,
|
|
||||||
'totalItems' => count($featured),
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'menu':
|
|
||||||
$menu = filter($content, function ($item) {
|
|
||||||
return $item['menu'] == true && $item['deleted'] == false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$result = ['pages' => $menu, 'totalItems' => count($menu)];
|
|
||||||
break;
|
|
||||||
case 'single':
|
|
||||||
$uuid = $args['fifth'];
|
|
||||||
$page = (new Book('../content/pages'))->findPageById($uuid);
|
|
||||||
|
|
||||||
$entry = [
|
|
||||||
'id' => $page['id'],
|
|
||||||
'uuid' => $page['uuid'],
|
|
||||||
'title' => $page['title'],
|
|
||||||
'feature' => $page['feature'],
|
|
||||||
'path' => $page['path'],
|
|
||||||
'layout' => $page['layout'],
|
|
||||||
'tags' => $page['tags'],
|
|
||||||
'author' => $page['author'],
|
|
||||||
'created' => $page['created'],
|
|
||||||
'updated' => $page['updated'],
|
|
||||||
'deleted' => $page['deleted'],
|
|
||||||
'menu' => $page['menu'],
|
|
||||||
'featured' => $page['featured'],
|
|
||||||
'published' => $page['published'],
|
|
||||||
'slug' => $page['slug'],
|
|
||||||
'content' => StringTools::sanitizeContent($page['content']),
|
|
||||||
];
|
|
||||||
$result = $entry;
|
|
||||||
break;
|
|
||||||
case 'tags':
|
|
||||||
$result = Settings::getTags();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$result = [
|
|
||||||
'message' => "Hm, no task. That's unfortunate",
|
|
||||||
'type' => 'TASK_NONE',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function handlePageTask($request, $args)
|
|
||||||
{
|
|
||||||
$task = $args['fourth'];
|
|
||||||
switch ($task) {
|
|
||||||
case 'delete':
|
|
||||||
case 'create':
|
|
||||||
case 'write':
|
|
||||||
$body = json_decode(file_get_contents("php://input"), true);
|
|
||||||
$passed = true;
|
|
||||||
if (!isset($body['form_token'])) {
|
|
||||||
$result = [
|
|
||||||
'message' => 'No form token. Not good, sport.',
|
|
||||||
'type' => 'TASK_FORM_AUTH',
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
if ($body['form_token'] == Session::get('form_token')) {
|
|
||||||
$keys = [
|
|
||||||
'id',
|
|
||||||
'uuid',
|
|
||||||
'layout',
|
|
||||||
'current_title',
|
|
||||||
'content',
|
|
||||||
'title',
|
|
||||||
'created',
|
|
||||||
'slug',
|
|
||||||
'tags',
|
|
||||||
'menu',
|
|
||||||
'featured',
|
|
||||||
'published',
|
|
||||||
'form_token',
|
|
||||||
'imageList',
|
|
||||||
"fileList",
|
|
||||||
"remote"
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($body as $key => $item) {
|
|
||||||
if (!in_array($key, $keys)) {
|
|
||||||
//found unnecessary key, so reject submission
|
|
||||||
var_dump($key);
|
|
||||||
$passed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($passed) {
|
|
||||||
$result = (new Book())->editPage($task, $request);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Unneccessary key found. Post not authorized, slick.',
|
|
||||||
'type' => 'TASK_FORM_AUTH',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Form token, auth failed. Uh oh.',
|
|
||||||
'type' => 'TASK_FORM_AUTH',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'add-entry-image':
|
|
||||||
$result = ImagesAPI::uploadImage($request);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$result = [
|
|
||||||
'message' => "Hm, no task. That's unfortunate",
|
|
||||||
'type' => 'TASK_NONE',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
147
brain/api/v1/SettingsAPI.inc.php
Normal file
147
brain/api/v1/SettingsAPI.inc.php
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Slim\Views\Twig;
|
||||||
|
|
||||||
|
class SettingsAPI
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function handleSettingsTask($request, $args, $body = null)
|
||||||
|
{
|
||||||
|
$task = $args["fourth"];
|
||||||
|
switch ($task) {
|
||||||
|
case "publish":
|
||||||
|
//check settings to see if site is a one pager
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$theme = $settings["global"]["theme"];
|
||||||
|
$themeConfig = json_decode(
|
||||||
|
file_get_contents("../content/themes/" . $theme . "/theme.json"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
//check to see if dynamic rendering is active
|
||||||
|
if (
|
||||||
|
isset($settings["global"]["dynamicRender"]) &&
|
||||||
|
$settings["global"]["dynamicRender"] === "true"
|
||||||
|
) {
|
||||||
|
$result = [
|
||||||
|
"message" => "Dynamic Render Active! You're good!",
|
||||||
|
"type" => "RENDER_SUCCESS",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$render = new Render();
|
||||||
|
if (isset($themeConfig["render"])) {
|
||||||
|
if (!$themeConfig["render"] || $themeConfig["render"] === "false") {
|
||||||
|
$render->renderIndex();
|
||||||
|
$result = [
|
||||||
|
"message" => "Index Rendered. HAND CLAPS",
|
||||||
|
"type" => "RENDER_SUCCESS",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$render->renderTags();
|
||||||
|
$render->renderArchive();
|
||||||
|
$render->renderPages();
|
||||||
|
$result = [
|
||||||
|
"message" => "Site Rendered. GOOD EFFORT",
|
||||||
|
"type" => "RENDER_SUCCESS",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// just incase the render flag is missing
|
||||||
|
$render->renderTags();
|
||||||
|
$render->renderArchive();
|
||||||
|
$render->renderPages();
|
||||||
|
$result = [
|
||||||
|
"message" => "Site Rendered. GOOD EFFORT",
|
||||||
|
"type" => "RENDER_SUCCESS",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if render flag is set and false, just render index page for one page sites
|
||||||
|
//otherwise, render all pages according to theme template files
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "add-avatar":
|
||||||
|
$result = ImagesAPI::uploadImage($request, "avatar");
|
||||||
|
break;
|
||||||
|
case "add-feature-background":
|
||||||
|
$result = ImagesAPI::uploadImage($request, "background");
|
||||||
|
break;
|
||||||
|
case "sync":
|
||||||
|
Settings::sync($body);
|
||||||
|
$result = [
|
||||||
|
"message" => "Settings Synced. You're doing great!",
|
||||||
|
"type" => "settingsUpdated",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case "nav-sync":
|
||||||
|
Settings::navSync($body);
|
||||||
|
$result = [
|
||||||
|
"message" => "Navigation updated. Very slick!",
|
||||||
|
"type" => "menuUpdated",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = [
|
||||||
|
"message" => "Hm, no task. That's unfortunate",
|
||||||
|
"type" => "TASK_NONE",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInfo($request, $args)
|
||||||
|
{
|
||||||
|
$task = $args["fourth"];
|
||||||
|
switch ($task) {
|
||||||
|
case "site":
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$data = [
|
||||||
|
"title" => $settings["global"]["title"],
|
||||||
|
"base_url" => $settings["global"]["base_url"],
|
||||||
|
"description" => $settings["global"]["descriptions"],
|
||||||
|
];
|
||||||
|
$result = [
|
||||||
|
"message" => "Settings Found",
|
||||||
|
"type" => "GET_SETTINGS",
|
||||||
|
"data" => $data,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case "member":
|
||||||
|
if (Session::active()) {
|
||||||
|
$member = $member = Session::get("member");
|
||||||
|
$data = ["handle" => $member["handle"], "email" => $member["email"]];
|
||||||
|
$result = [
|
||||||
|
"message" => "Member Info Found",
|
||||||
|
"type" => "GET_MEMBER_INFO",
|
||||||
|
"data" => $data,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Not logged in. C'mon, bruh",
|
||||||
|
"type" => "TASK_NONE",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = [
|
||||||
|
"message" => "No Settings found. Frowny Face",
|
||||||
|
"type" => "TASK_NONE",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createBackup()
|
||||||
|
{
|
||||||
|
$result = Maintenance::makeBackup();
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,153 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\api\v1;
|
|
||||||
|
|
||||||
use brain\data\Render;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use brain\data\Session;
|
|
||||||
use brain\utility\Maintenance;
|
|
||||||
|
|
||||||
class SettingsAPI
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function handleSettingsTask($request, $args, $body = null)
|
|
||||||
{
|
|
||||||
$task = $args['fourth'];
|
|
||||||
switch ($task) {
|
|
||||||
case 'publish':
|
|
||||||
//check settings to see if site is a one pager
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$theme = $settings['global']['theme'];
|
|
||||||
$themeConfig = json_decode(
|
|
||||||
file_get_contents('../content/themes/' . $theme . '/theme.json'),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
//check to see if dynamic rendering is active
|
|
||||||
if (
|
|
||||||
isset($settings['global']['dynamicRender']) &&
|
|
||||||
$settings['global']['dynamicRender'] === 'true'
|
|
||||||
) {
|
|
||||||
$result = [
|
|
||||||
'message' => "Dynamic Render Active! You're good!",
|
|
||||||
'type' => 'RENDER_SUCCESS',
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$render = new Render();
|
|
||||||
if (isset($themeConfig['render'])) {
|
|
||||||
//rendering for one page sites
|
|
||||||
if (!$themeConfig['render'] || $themeConfig['render'] === 'false') {
|
|
||||||
$render->renderIndex();
|
|
||||||
$result = [
|
|
||||||
'message' => 'Index Rendered. HAND CLAPS',
|
|
||||||
'type' => 'RENDER_SUCCESS',
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$render->renderTags();
|
|
||||||
$render->renderArchive();
|
|
||||||
$render->renderPages();
|
|
||||||
$result = [
|
|
||||||
'message' => 'Site Rendered. GOOD EFFORT',
|
|
||||||
'type' => 'RENDER_SUCCESS',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// just incase the render flag is missing
|
|
||||||
$render->renderTags();
|
|
||||||
$render->renderArchive();
|
|
||||||
$render->renderPages();
|
|
||||||
$result = [
|
|
||||||
'message' => 'Site Rendered. GOOD EFFORT',
|
|
||||||
'type' => 'RENDER_SUCCESS',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if render flag is set and false, just render index page for one page sites
|
|
||||||
//otherwise, render all pages according to theme template files
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'add-avatar':
|
|
||||||
$result = ImagesAPI::uploadImage($request, 'avatar');
|
|
||||||
break;
|
|
||||||
case 'add-feature-background':
|
|
||||||
$result = ImagesAPI::uploadImage($request, 'background');
|
|
||||||
break;
|
|
||||||
case 'sync':
|
|
||||||
Settings::sync($body);
|
|
||||||
$result = [
|
|
||||||
'message' => "Settings Synced. You're doing great!",
|
|
||||||
'type' => 'settingsUpdated',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'nav-sync':
|
|
||||||
Settings::navSync($body);
|
|
||||||
$result = [
|
|
||||||
'message' => 'Navigation updated. Very slick!',
|
|
||||||
'type' => 'menuUpdated',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$result = [
|
|
||||||
'message' => "Hm, no task. That's unfortunate",
|
|
||||||
'type' => 'TASK_NONE',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getInfo($request, $args)
|
|
||||||
{
|
|
||||||
$task = $args['fourth'];
|
|
||||||
switch ($task) {
|
|
||||||
case 'site':
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$data = [
|
|
||||||
'title' => $settings['global']['title'],
|
|
||||||
'base_url' => $settings['global']['base_url'],
|
|
||||||
'description' => $settings['global']['descriptions'],
|
|
||||||
];
|
|
||||||
$result = [
|
|
||||||
'message' => 'Settings Found',
|
|
||||||
'type' => 'GET_SETTINGS',
|
|
||||||
'data' => $data,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'member':
|
|
||||||
if (Session::active()) {
|
|
||||||
$member = $member = Session::get('member');
|
|
||||||
$data = ['handle' => $member['handle'], 'email' => $member['email']];
|
|
||||||
$result = [
|
|
||||||
'message' => 'Member Info Found',
|
|
||||||
'type' => 'GET_MEMBER_INFO',
|
|
||||||
'data' => $data,
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => "Not logged in. C'mon, bruh",
|
|
||||||
'type' => 'TASK_NONE',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$result = [
|
|
||||||
'message' => 'No Settings found. Frowny Face',
|
|
||||||
'type' => 'TASK_NONE',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function createBackup()
|
|
||||||
{
|
|
||||||
$result = Maintenance::makeBackup();
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
227
brain/controller/APIControl.inc.php
Normal file
227
brain/controller/APIControl.inc.php
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
<?php
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
include "../brain/api/v1/AuthAPI.inc.php";
|
||||||
|
include "../brain/api/v1/ImagesAPI.inc.php";
|
||||||
|
include "../brain/api/v1/PagesAPI.inc.php";
|
||||||
|
include "../brain/api/v1/SettingsAPI.inc.php";
|
||||||
|
include "../brain/api/v1/InitAPI.inc.php";
|
||||||
|
include "../brain/api/v1/MailerAPI.inc.php";
|
||||||
|
|
||||||
|
class APIControl
|
||||||
|
{
|
||||||
|
public static function get(
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
array $args
|
||||||
|
): ResponseInterface {
|
||||||
|
$filename = "";
|
||||||
|
switch (isset($args["third"]) ? $args["third"] : "none") {
|
||||||
|
case "status":
|
||||||
|
$result = AuthAPI::status();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "page":
|
||||||
|
//echo
|
||||||
|
if (Member::verifyKey($_GET["key"])) {
|
||||||
|
$result = PagesAPI::getPageContent($request, $args);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "settings":
|
||||||
|
$token = $request->getHeader("fipamo-access-token");
|
||||||
|
//Verify token to get site info
|
||||||
|
if (isset($token[0])) {
|
||||||
|
if (Session::verifyToken($token[0])) {
|
||||||
|
$result = SettingsAPI::getInfo($request, $args);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Invalid token, API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "No token, API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "files":
|
||||||
|
if (Session::active()) {
|
||||||
|
if ($args["third"] == "backup") {
|
||||||
|
$filename = "../config/backups/latest_backup.zip";
|
||||||
|
if (file_exists($filename)) {
|
||||||
|
header("Content-Type: application/zip");
|
||||||
|
header(
|
||||||
|
'Content-Disposition: attachment; filename="' .
|
||||||
|
basename($filename) .
|
||||||
|
'"'
|
||||||
|
);
|
||||||
|
header("Content-Length: " . filesize($filename));
|
||||||
|
|
||||||
|
flush();
|
||||||
|
// return readfile($filename);
|
||||||
|
//readfile($filename);
|
||||||
|
// delete file
|
||||||
|
//unlink($filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$freshResponse = $response;
|
||||||
|
|
||||||
|
if ($args["third"] == "files") {
|
||||||
|
$freshResponse
|
||||||
|
->getBody()
|
||||||
|
->write(file_get_contents("../config/backups/latest_back.zip"));
|
||||||
|
|
||||||
|
$freshResponse->withHeader("Content-Type", "application/zip");
|
||||||
|
return $freshResponse->withAddedHeader(
|
||||||
|
"Content-Disposition",
|
||||||
|
"attachment; filename=latest_backup.zip"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$response->getBody()->write(json_encode($result));
|
||||||
|
return $response->withHeader("Content-Type", "application/json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static function post(
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
array $args
|
||||||
|
): ResponseInterface {
|
||||||
|
$contentType = $request->getHeader("Content-Type");
|
||||||
|
switch ($contentType[0]) {
|
||||||
|
case "application/json":
|
||||||
|
$body = json_decode(file_get_contents("php://input"), true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (isset($args["third"]) ? $args["third"] : "none") {
|
||||||
|
case "restore": //move to 'api/auth'
|
||||||
|
case "init": //move to 'api/auth'
|
||||||
|
$task = $args["third"];
|
||||||
|
$result = InitApi::handleInitTasks(
|
||||||
|
$task,
|
||||||
|
$task == "init" ? $body : $request
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "backup": //move to 'api/auth'
|
||||||
|
$token = $request->getHeader("fipamo-access-token");
|
||||||
|
//Verify token for admin tasks
|
||||||
|
$result = SettingsAPI::createBackup();
|
||||||
|
/*
|
||||||
|
|
||||||
|
if (Session::verifyToken($token[0])) {
|
||||||
|
$result = SettingsAPI::createBackup();
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case "login": //move to 'api/auth'
|
||||||
|
//check if request is remote and if so, verify token
|
||||||
|
if ($body["remote"] || $body["remote"] == "true") {
|
||||||
|
if (Member::verifyKey($body["key"])) {
|
||||||
|
$result = AuthAPI::login($body);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//request is local, so it's cool
|
||||||
|
$result = AuthAPI::login($body);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "logout": //move to 'api/auth'
|
||||||
|
$result = AuthAPI::logout($body);
|
||||||
|
break;
|
||||||
|
case "get-secret": //move to 'api/auth'
|
||||||
|
$result = AuthAPI::requestSecret($body);
|
||||||
|
break;
|
||||||
|
case "reset-password": //move to 'api/auth'
|
||||||
|
$result = AuthAPI::resetPassword($body);
|
||||||
|
break;
|
||||||
|
case "page":
|
||||||
|
$token = $request->getHeader("fipamo-access-token");
|
||||||
|
//Verify token for admin tasks
|
||||||
|
if (isset($token[0])) {
|
||||||
|
if (Session::verifyToken($token[0])) {
|
||||||
|
$result = PagesAPI::handlePageTask($request, $args);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Invalid token, API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "No token, API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "settings":
|
||||||
|
if (isset($body)) {
|
||||||
|
$postBody = $body;
|
||||||
|
} else {
|
||||||
|
$postBody = null;
|
||||||
|
}
|
||||||
|
$task = $args["fourth"];
|
||||||
|
if ($task == "add-feature-background" || $task == "add-avatar") {
|
||||||
|
$result = SettingsAPI::handleSettingsTask($request, $args, $postBody);
|
||||||
|
} else {
|
||||||
|
$token = $request->getHeader("fipamo-access-token");
|
||||||
|
if (Session::verifyToken($token[0])) {
|
||||||
|
$result = SettingsAPI::handleSettingsTask(
|
||||||
|
$request,
|
||||||
|
$args,
|
||||||
|
$postBody
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "API access denied, homie",
|
||||||
|
"type" => "API_ERROR",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "mailer":
|
||||||
|
$result = MailerAPI::handleMail($request, $body, $response);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result = [
|
||||||
|
"message" => "Oh, nothing to do. That's unfortunate",
|
||||||
|
"type" => "TASK_NONE",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->getBody()->write(json_encode($result));
|
||||||
|
return $response->withHeader("Content-Type", "application/json");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,250 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\controller;
|
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use brain\api\v1\AuthAPI;
|
|
||||||
use brain\api\v1\PagesAPI;
|
|
||||||
use brain\api\v1\FilesAPI;
|
|
||||||
use brain\api\v1\SettingsAPI;
|
|
||||||
use brain\api\v1\InitAPI;
|
|
||||||
use brain\api\v1\MailerAPI;
|
|
||||||
use brain\data\Member;
|
|
||||||
use brain\data\Session;
|
|
||||||
|
|
||||||
class APIControl
|
|
||||||
{
|
|
||||||
public static function get(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
ResponseInterface $response,
|
|
||||||
array $args
|
|
||||||
): ResponseInterface {
|
|
||||||
$filename = '';
|
|
||||||
switch (isset($args['third']) ? $args['third'] : 'none') {
|
|
||||||
case 'status':
|
|
||||||
$result = AuthAPI::status();
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'page':
|
|
||||||
//echo
|
|
||||||
if (Member::verifyKey($_GET['key'])) {
|
|
||||||
$result = PagesAPI::getPageContent($request, $args);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'settings':
|
|
||||||
$token = $request->getHeader('fipamo-access-token');
|
|
||||||
//Verify token to get site info
|
|
||||||
if (isset($token[0])) {
|
|
||||||
if (Session::verifyToken($token[0])) {
|
|
||||||
$result = SettingsAPI::getInfo($request, $args);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Invalid token, API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'No token, API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'files':
|
|
||||||
if (Session::active()) {
|
|
||||||
if ($args['third'] == 'backup') {
|
|
||||||
$filename = '../config/backups/latest_backup.zip';
|
|
||||||
if (file_exists($filename)) {
|
|
||||||
header('Content-Type: application/zip');
|
|
||||||
header(
|
|
||||||
'Content-Disposition: attachment; filename="' .
|
|
||||||
basename($filename) .
|
|
||||||
'"'
|
|
||||||
);
|
|
||||||
header('Content-Length: ' . filesize($filename));
|
|
||||||
|
|
||||||
flush();
|
|
||||||
// return readfile($filename);
|
|
||||||
//readfile($filename);
|
|
||||||
// delete file
|
|
||||||
//unlink($filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
// no break
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$freshResponse = $response;
|
|
||||||
|
|
||||||
if ($args['third'] == 'files') {
|
|
||||||
$freshResponse
|
|
||||||
->getBody()
|
|
||||||
->write(file_get_contents('../config/backups/latest_back.zip'));
|
|
||||||
|
|
||||||
$freshResponse->withHeader('Content-Type', 'application/zip');
|
|
||||||
return $freshResponse->withAddedHeader(
|
|
||||||
'Content-Disposition',
|
|
||||||
'attachment; filename=latest_backup.zip'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$response->getBody()->write(json_encode($result));
|
|
||||||
return $response->withHeader('Content-Type', 'application/json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function post(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
ResponseInterface $response,
|
|
||||||
array $args
|
|
||||||
): ResponseInterface {
|
|
||||||
$contentType = $request->getHeader('Content-Type');
|
|
||||||
switch ($contentType[0]) {
|
|
||||||
case 'application/json':
|
|
||||||
$body = json_decode(file_get_contents('php://input'), true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (isset($args['third']) ? $args['third'] : 'none') {
|
|
||||||
case 'restore': //move to 'api/auth'
|
|
||||||
case 'init': //move to 'api/auth'
|
|
||||||
$task = $args['third'];
|
|
||||||
$result = InitApi::handleInitTasks(
|
|
||||||
$task,
|
|
||||||
$task == 'init' ? $body : $request
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'backup': //move to 'api/auth'
|
|
||||||
$token = $request->getHeader('fipamo-access-token');
|
|
||||||
//Verify token for admin tasks
|
|
||||||
$result = SettingsAPI::createBackup();
|
|
||||||
/*
|
|
||||||
|
|
||||||
if (Session::verifyToken($token[0])) {
|
|
||||||
$result = SettingsAPI::createBackup();
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
"message" => "API access denied, homie",
|
|
||||||
"type" => "API_ERROR",
|
|
||||||
];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
case 'login': //move to 'api/auth'
|
|
||||||
//check if request is remote and if so, verify token
|
|
||||||
if ($body['remote'] || $body['remote'] == 'true') {
|
|
||||||
if (Member::verifyKey($body['key'])) {
|
|
||||||
$result = AuthAPI::login($body);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//request is local, so it's cool
|
|
||||||
$result = AuthAPI::login($body);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'logout': //move to 'api/auth'
|
|
||||||
$result = AuthAPI::logout($body);
|
|
||||||
break;
|
|
||||||
case 'get-secret': //move to 'api/auth'
|
|
||||||
$result = AuthAPI::requestSecret($body);
|
|
||||||
break;
|
|
||||||
case 'reset-password': //move to 'api/auth'
|
|
||||||
$result = AuthAPI::resetPassword($body);
|
|
||||||
break;
|
|
||||||
case 'page':
|
|
||||||
$token = $request->getHeader('fipamo-access-token');
|
|
||||||
//Verify token for admin tasks
|
|
||||||
if (isset($token[0])) {
|
|
||||||
if (Session::verifyToken($token[0])) {
|
|
||||||
$result = PagesAPI::handlePageTask($request, $args);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Invalid token, API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'No token, API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "files":
|
|
||||||
$token = $request->getHeader('fipamo-access-token');
|
|
||||||
if (isset($token[0])) {
|
|
||||||
if (Session::verifyToken($token[0])) {
|
|
||||||
$result = FilesAPI::uploadFiles($request, $args);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Invalid token, API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'No token, API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'settings':
|
|
||||||
if (isset($body)) {
|
|
||||||
$postBody = $body;
|
|
||||||
} else {
|
|
||||||
$postBody = null;
|
|
||||||
}
|
|
||||||
$task = $args['fourth'];
|
|
||||||
if ($task == 'add-feature-background' || $task == 'add-avatar') {
|
|
||||||
$result = SettingsAPI::handleSettingsTask($request, $args, $postBody);
|
|
||||||
} else {
|
|
||||||
$token = $request->getHeader('fipamo-access-token');
|
|
||||||
if (Session::verifyToken($token[0])) {
|
|
||||||
$result = SettingsAPI::handleSettingsTask(
|
|
||||||
$request,
|
|
||||||
$args,
|
|
||||||
$postBody
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'API access denied, homie',
|
|
||||||
'type' => 'API_ERROR',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'mailer':
|
|
||||||
$result = MailerAPI::handleMail($request, $body, $response);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$result = [
|
|
||||||
'message' => "Oh, nothing to do. That's unfortunate",
|
|
||||||
'type' => 'TASK_NONE',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$response->getBody()->write(json_encode($result));
|
|
||||||
return $response->withHeader('Content-Type', 'application/json');
|
|
||||||
}
|
|
||||||
}
|
|
186
brain/controller/DashControl.inc.php
Normal file
186
brain/controller/DashControl.inc.php
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<?php
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Slim\Views\Twig;
|
||||||
|
|
||||||
|
include "../brain/data/Book.inc.php";
|
||||||
|
|
||||||
|
class DashControl
|
||||||
|
{
|
||||||
|
public static function start(
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
array $args
|
||||||
|
): ResponseInterface {
|
||||||
|
$view = Twig::fromRequest($request);
|
||||||
|
$pageOptions = [];
|
||||||
|
$template = "";
|
||||||
|
if (Setup::status()) {
|
||||||
|
switch (isset($args["second"]) ? $args["second"] : "index") {
|
||||||
|
case "settings":
|
||||||
|
if (Session::active()) {
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$themes = (new Themes())->getThemes(); //$config->getThemes();
|
||||||
|
$template = "dash/settings.twig";
|
||||||
|
$member = Session::get("member");
|
||||||
|
$form_token = Session::get("form_token");
|
||||||
|
$updated = new \Moment\Moment($settings["global"]["last_backup"]);
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Dash Settings",
|
||||||
|
"private" => $settings["global"]["private"],
|
||||||
|
"renderOnSave" => $settings["global"]["renderOnSave"],
|
||||||
|
"background" => $settings["global"]["background"],
|
||||||
|
"member" => $member,
|
||||||
|
"ftoken" => $form_token,
|
||||||
|
"siteTitle" => $settings["global"]["title"],
|
||||||
|
"baseUrl" => $settings["global"]["base_url"],
|
||||||
|
"desc" => $settings["global"]["descriptions"],
|
||||||
|
"lastBackup" => $updated->format("Y M D d"),
|
||||||
|
"currentTheme" => $settings["global"]["theme"],
|
||||||
|
"themes" => $themes,
|
||||||
|
"apiStatus" => isset($settings["global"]["externalAPI"])
|
||||||
|
? $settings["global"]["externalAPI"]
|
||||||
|
: "false",
|
||||||
|
"dynamicRenderStatus" => isset(
|
||||||
|
$settings["global"]["dynamicRender"]
|
||||||
|
)
|
||||||
|
? $settings["global"]["dynamicRender"]
|
||||||
|
: "false",
|
||||||
|
"mailOption" => $settings["email"]["active"],
|
||||||
|
"mailConfig" => $settings["email"],
|
||||||
|
"status" => Session::active(),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
header("Location: /dashboard");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "navigation":
|
||||||
|
if (Session::active()) {
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$template = "dash/navigation.twig";
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Edit Dash Navigation",
|
||||||
|
"status" => Session::active(),
|
||||||
|
"menu" => $settings["menu"],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
header("Location: /dashboard");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "pages":
|
||||||
|
if (Session::active()) {
|
||||||
|
$currentPage = isset($args["fourth"]) ? $args["fourth"] : 1;
|
||||||
|
$filter = isset($args["third"]) ? $args["third"] : "all";
|
||||||
|
$data = (new Book("../content/pages"))->getPages(
|
||||||
|
$currentPage,
|
||||||
|
4,
|
||||||
|
$filter
|
||||||
|
);
|
||||||
|
$template = "dash/book.twig";
|
||||||
|
$pageOptions = [
|
||||||
|
"entryCount" => $data["entryCount"],
|
||||||
|
"numOfPages" => $data["numOfPages"],
|
||||||
|
"currentPage" => $currentPage,
|
||||||
|
"filter" => $data["paginate"]["sort"],
|
||||||
|
"stats" => $data["stats"],
|
||||||
|
"pages" => $data["pages"],
|
||||||
|
"paginate" => $data["paginate"],
|
||||||
|
"status" => Session::active(),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
header("Location: /dashboard");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "page":
|
||||||
|
if (Session::active()) {
|
||||||
|
$template = "dash/page-edit.twig";
|
||||||
|
$mode = $args["third"];
|
||||||
|
$uuid = $args["fourth"];
|
||||||
|
switch ($mode) {
|
||||||
|
case "edit":
|
||||||
|
$customPages = (new Themes())->getCustomViews();
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Fipamo | Edit Page",
|
||||||
|
"page" => (new Book("../content/pages"))->findPageById($uuid),
|
||||||
|
"mode" => $mode,
|
||||||
|
"token" => Session::get("form_token"),
|
||||||
|
"status" => Session::active(),
|
||||||
|
"views" => $customPages,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case "preview":
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$loader = new \Twig\Loader\FilesystemLoader(
|
||||||
|
"../content/themes"
|
||||||
|
);
|
||||||
|
$display = new \Twig\Environment($loader, []);
|
||||||
|
|
||||||
|
$book = new Book("../content/pages");
|
||||||
|
$page = $book->findPageById($uuid);
|
||||||
|
$pageOptions = Sorting::page($page);
|
||||||
|
$preview =
|
||||||
|
$settings["global"]["theme"] .
|
||||||
|
"/" .
|
||||||
|
$page["layout"] .
|
||||||
|
".twig";
|
||||||
|
$html = $display->render($preview, $pageOptions);
|
||||||
|
$response->getBody()->write($html);
|
||||||
|
return $response;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Fipamo | Create Page",
|
||||||
|
"token" => Session::get("form_token"),
|
||||||
|
"mode" => $mode,
|
||||||
|
"status" => Session::active(),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
header("Location: /dashboard");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "logout":
|
||||||
|
Session::kill();
|
||||||
|
header("Location: /dashboard");
|
||||||
|
die();
|
||||||
|
break;
|
||||||
|
case "reset-password":
|
||||||
|
$template = "dash/reset-password.twig";
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Reset Password",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$template = "dash/start.twig";
|
||||||
|
if (Session::active()) {
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Welcome Back",
|
||||||
|
"status" => Session::active(),
|
||||||
|
"data" => (new Book("../content/pages"))->getPages(1, 4),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Welcome to Fipamo",
|
||||||
|
"status" => Session::active(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$template = "dash/init.twig";
|
||||||
|
$pageOptions = ["title" => "Fipamo Setup"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $view->render($response, $template, $pageOptions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,226 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\controller;
|
|
||||||
|
|
||||||
use brain\data\Book;
|
|
||||||
use brain\data\Session;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use brain\data\Themes;
|
|
||||||
use brain\utility\Setup;
|
|
||||||
use brain\utility\Sorting;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use Slim\Views\Twig;
|
|
||||||
|
|
||||||
class DashControl
|
|
||||||
{
|
|
||||||
public static function start(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
ResponseInterface $response,
|
|
||||||
array $args
|
|
||||||
): ResponseInterface {
|
|
||||||
$view = Twig::fromRequest($request);
|
|
||||||
$pageOptions = [];
|
|
||||||
$template = '';
|
|
||||||
if (Setup::status()) {
|
|
||||||
switch (isset($args['second']) ? $args['second'] : 'index') {
|
|
||||||
case 'settings':
|
|
||||||
if (Session::active()) {
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$themes = (new Themes())->getThemes(); // $config->getThemes();
|
|
||||||
$template = 'dash/settings.twig';
|
|
||||||
$member = Session::get('member');
|
|
||||||
$form_token = Session::get('form_token');
|
|
||||||
$updated = new Carbon($settings['global']['last_backup']);
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Settings',
|
|
||||||
'private' => $settings['global']['private'],
|
|
||||||
'renderOnSave' => $settings['global']['renderOnSave'],
|
|
||||||
'background' => $settings['global']['background'],
|
|
||||||
'member' => $member,
|
|
||||||
'ftoken' => $form_token,
|
|
||||||
'siteTitle' => $settings['global']['title'],
|
|
||||||
'baseUrl' => $settings['global']['base_url'],
|
|
||||||
'desc' => $settings['global']['descriptions'],
|
|
||||||
'lastBackup' => $updated->format('Y M D d'),
|
|
||||||
'currentTheme' => $settings['global']['theme'],
|
|
||||||
'themes' => $themes,
|
|
||||||
'apiStatus' => isset($settings['global']['externalAPI'])
|
|
||||||
? $settings['global']['externalAPI']
|
|
||||||
: 'false',
|
|
||||||
'dynamicRenderStatus' => isset(
|
|
||||||
$settings['global']['dynamicRender']
|
|
||||||
)
|
|
||||||
? $settings['global']['dynamicRender']
|
|
||||||
: 'false',
|
|
||||||
'mailOption' => $settings['email']['active'],
|
|
||||||
'mailConfig' => $settings['email'],
|
|
||||||
'status' => Session::active(),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
header('Location: /dashboard');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'navigation':
|
|
||||||
if (Session::active()) {
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$template = 'dash/navigation.twig';
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Edit Menu',
|
|
||||||
'status' => Session::active(),
|
|
||||||
'menu' => $settings['menu'],
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
header('Location: /dashboard');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'pages':
|
|
||||||
if (Session::active()) {
|
|
||||||
$currentPage = isset($args['fourth']) ? $args['fourth'] : 1;
|
|
||||||
$filter = isset($args['third']) ? $args['third'] : 'all';
|
|
||||||
$data = (new Book())->getPages($currentPage, 4, $filter);
|
|
||||||
$template = 'dash/book.twig';
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Contents',
|
|
||||||
'entryCount' => $data['entryCount'],
|
|
||||||
'numOfPages' => $data['numOfPages'],
|
|
||||||
'currentPage' => $currentPage,
|
|
||||||
'filter' => $data['paginate']['sort'],
|
|
||||||
'stats' => $data['stats'],
|
|
||||||
'pages' => $data['pages'],
|
|
||||||
'paginate' => $data['paginate'],
|
|
||||||
'status' => Session::active(),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
header('Location: /dashboard');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'page':
|
|
||||||
if (Session::active()) {
|
|
||||||
$template = 'dash/page-edit.twig';
|
|
||||||
$mode = $args['third'];
|
|
||||||
$uuid = $args['fourth'];
|
|
||||||
|
|
||||||
switch ($mode) {
|
|
||||||
case 'edit':
|
|
||||||
$page = (new Book())->findPageById($uuid);
|
|
||||||
$views = [];
|
|
||||||
if (!isset($page['layout'])) {
|
|
||||||
$page['layout'] = "page";
|
|
||||||
}
|
|
||||||
if (str_contains($page['layout'], 'index')) {
|
|
||||||
$views = (new Themes())->getCustomIndex();
|
|
||||||
} else {
|
|
||||||
$views = (new Themes())->getCustomViews();
|
|
||||||
}
|
|
||||||
$imageList = [];
|
|
||||||
$fileList = [];
|
|
||||||
if (isset($page['feature'])) {
|
|
||||||
$imageList = explode(',', $page['feature']);
|
|
||||||
}
|
|
||||||
if (isset($page['files'])) {
|
|
||||||
$fileList = explode(',', $page['files']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$images = [];
|
|
||||||
$files = [];
|
|
||||||
foreach ($imageList as $item) {
|
|
||||||
$image = trim($item);
|
|
||||||
if (!empty($image)) {
|
|
||||||
array_push($images, $image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($fileList as $item) {
|
|
||||||
$file = trim($item);
|
|
||||||
if (!empty($file)) {
|
|
||||||
array_push($files, $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => $page['title'],
|
|
||||||
'page' => $page,
|
|
||||||
'mode' => $mode,
|
|
||||||
'token' => Session::get('form_token'),
|
|
||||||
'status' => Session::active(),
|
|
||||||
'images' => $images,
|
|
||||||
'files' => $files,
|
|
||||||
'views' => $views,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'preview':
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$loader = new \Twig\Loader\FilesystemLoader(
|
|
||||||
'../content/themes/' . $settings['global']['theme'] .
|
|
||||||
'/'
|
|
||||||
);
|
|
||||||
$display = new \Twig\Environment($loader, []);
|
|
||||||
|
|
||||||
$book = new Book();
|
|
||||||
$page = $book->findPageById($uuid);
|
|
||||||
$pageOptions = Sorting::page($page);
|
|
||||||
$preview = $page['layout'] .
|
|
||||||
'.twig';
|
|
||||||
$html = $display->render($preview, $pageOptions);
|
|
||||||
$response->getBody()->write($html);
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Fipamo | Create Page',
|
|
||||||
'token' => Session::get('form_token'),
|
|
||||||
'mode' => $mode,
|
|
||||||
'status' => Session::active(),
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
header('Location: /dashboard');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'logout':
|
|
||||||
Session::kill();
|
|
||||||
header('Location: /dashboard');
|
|
||||||
exit();
|
|
||||||
break;
|
|
||||||
case 'reset-password':
|
|
||||||
$template = 'dash/reset-password.twig';
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Reset Password',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$template = 'dash/start.twig';
|
|
||||||
if (Session::active()) {
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Start',
|
|
||||||
'status' => Session::active(),
|
|
||||||
'data' => (new Book())->getPages(1, 4),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Welcome to Fipamo',
|
|
||||||
'status' => Session::active(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$template = 'dash/init.twig';
|
|
||||||
$pageOptions = ['title' => 'Fipamo Setup'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $view->render($response, $template, $pageOptions);
|
|
||||||
}
|
|
||||||
}
|
|
99
brain/controller/IndexControl.inc.php
Normal file
99
brain/controller/IndexControl.inc.php
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Slim\Views\Twig;
|
||||||
|
use function _\find;
|
||||||
|
|
||||||
|
class IndexControl
|
||||||
|
{
|
||||||
|
public static function start(
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
array $args
|
||||||
|
): ResponseInterface {
|
||||||
|
//unset($_SESSION);
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$view = Twig::fromRequest($request);
|
||||||
|
//checks dynamic render flag for site render status
|
||||||
|
if ($settings["global"]["dynamicRender"]) {
|
||||||
|
if ($settings["global"]["dynamicRender"] == "true") {
|
||||||
|
$loader = new \Twig\Loader\FilesystemLoader("../content/themes");
|
||||||
|
$display = new \Twig\Environment($loader, []);
|
||||||
|
$template = "";
|
||||||
|
$pageOptions = [];
|
||||||
|
|
||||||
|
$pageInfo = [
|
||||||
|
"keywords" => isset($settings["global"]["keywords"])
|
||||||
|
? $settings["global"]["keywords"]
|
||||||
|
: "fipamo, blog, jamstack, php, markdown, js",
|
||||||
|
"description" => $settings["global"]["descriptions"],
|
||||||
|
"image" =>
|
||||||
|
$settings["global"]["base_url"] . $settings["global"]["background"],
|
||||||
|
"baseURL" => $settings["global"]["base_url"],
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isset($args["first"])) {
|
||||||
|
switch ($args["first"]) {
|
||||||
|
case "tags":
|
||||||
|
$template = $settings["global"]["theme"] . "/tags.twig";
|
||||||
|
$tag = trim($args["second"]);
|
||||||
|
$taglist = Sorting::tags();
|
||||||
|
$item = find($taglist, ["tag_name" => $tag]);
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Pages Tagged as " . $item["tag_name"],
|
||||||
|
"background" => $pageInfo["image"],
|
||||||
|
"tag_list" => $item["pages"],
|
||||||
|
"info" => $pageInfo,
|
||||||
|
"menu" => $settings["menu"],
|
||||||
|
"dynamicRender" => $settings["global"]["dynamicRender"],
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case "archives":
|
||||||
|
$archive = Sorting::archive();
|
||||||
|
$template = $settings["global"]["theme"] . "/archive.twig";
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Archive",
|
||||||
|
"background" => $pageInfo["image"],
|
||||||
|
"archives" => $archive,
|
||||||
|
"info" => $pageInfo,
|
||||||
|
"menu" => $settings["menu"],
|
||||||
|
"dynamicRender" => $settings["global"]["dynamicRender"],
|
||||||
|
];
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//check layout to see what page should be rendered
|
||||||
|
$template = $settings["global"]["theme"] . "/page.twig";
|
||||||
|
$book = new Book("../content/pages");
|
||||||
|
$page = $book->findPageBySlug($args["third"]);
|
||||||
|
$pageOptions = Sorting::page($page);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//index
|
||||||
|
$template = $settings["global"]["theme"] . "/index.twig";
|
||||||
|
$book = new Book("../content/pages");
|
||||||
|
$page = $book->findPageBySlug();
|
||||||
|
$pageOptions = Sorting::page($page);
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = $display->render($template, $pageOptions);
|
||||||
|
$response->getBody()->write($html);
|
||||||
|
return $response;
|
||||||
|
} else {
|
||||||
|
$view = Twig::fromRequest($request);
|
||||||
|
$html = file_get_contents("../public/index.html");
|
||||||
|
$response->getBody()->write($html);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//if flag is not present, default to static html
|
||||||
|
$view = Twig::fromRequest($request);
|
||||||
|
$html = file_get_contents("../public/index.html");
|
||||||
|
$response->getBody()->write($html);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,110 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\controller;
|
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use Slim\Views\Twig;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use brain\utility\Sorting;
|
|
||||||
|
|
||||||
use function _\find;
|
|
||||||
|
|
||||||
class IndexControl
|
|
||||||
{
|
|
||||||
public static function start(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
ResponseInterface $response,
|
|
||||||
array $args
|
|
||||||
): ResponseInterface {
|
|
||||||
//unset($_SESSION);
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$view = Twig::fromRequest($request);
|
|
||||||
//checks dynamic render flag for site render status
|
|
||||||
if ($settings['global']['dynamicRender']) {
|
|
||||||
if ($settings['global']['dynamicRender'] == 'true') {
|
|
||||||
$loader = new \Twig\Loader\FilesystemLoader('../content/themes');
|
|
||||||
$display = new \Twig\Environment($loader, []);
|
|
||||||
$template = '';
|
|
||||||
$pageOptions = [];
|
|
||||||
|
|
||||||
$pageInfo = [
|
|
||||||
'keywords' => isset($settings['global']['keywords'])
|
|
||||||
? $settings['global']['keywords']
|
|
||||||
: 'fipamo, blog, jamstack, php, markdown, js',
|
|
||||||
'description' => $settings['global']['descriptions'],
|
|
||||||
'image' => $settings['global']['base_url'] . $settings['global']['background'],
|
|
||||||
'baseURL' => $settings['global']['base_url'],
|
|
||||||
];
|
|
||||||
|
|
||||||
if (isset($args['first'])) {
|
|
||||||
switch ($args['first']) {
|
|
||||||
case 'tags':
|
|
||||||
$template = $settings['global']['theme'] . '/tags.twig';
|
|
||||||
$tag = trim($args['second']);
|
|
||||||
$taglist = Sorting::tags();
|
|
||||||
$item = find($taglist, ['tag_name' => $tag]);
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Pages Tagged as ' . $item['tag_name'],
|
|
||||||
'background' => $pageInfo['image'],
|
|
||||||
'tag_list' => $item['pages'],
|
|
||||||
'info' => $pageInfo,
|
|
||||||
'menu' => $settings['menu'],
|
|
||||||
'dynamicRender' => $settings['global']['dynamicRender'],
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'archives':
|
|
||||||
$archive = Sorting::archive();
|
|
||||||
$template = $settings['global']['theme'] . '/archive.twig';
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Archive',
|
|
||||||
'background' => $pageInfo['image'],
|
|
||||||
'archives' => $archive,
|
|
||||||
'info' => $pageInfo,
|
|
||||||
'menu' => $settings['menu'],
|
|
||||||
'dynamicRender' => $settings['global']['dynamicRender'],
|
|
||||||
];
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//check if page is a menu item, if not render along path as usual
|
|
||||||
$page = [];
|
|
||||||
$book = new Book();
|
|
||||||
if (is_numeric($args['first'])) {
|
|
||||||
$page = $book->findPageBySlug($args['third']);
|
|
||||||
} else {
|
|
||||||
$page = $book->findPageBySlug($args['first']);
|
|
||||||
}
|
|
||||||
$template = $settings['global']['theme'] . '/' . $page['layout'] . '.twig';
|
|
||||||
$pageOptions = Sorting::page($page);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//index
|
|
||||||
$template = $settings['global']['theme'] . '/' . $page['layout'] . '.twig';
|
|
||||||
$book = new Book('');
|
|
||||||
$page = $book->findPageBySlug();
|
|
||||||
$pageOptions = Sorting::page($page);
|
|
||||||
}
|
|
||||||
|
|
||||||
$html = $display->render($template, $pageOptions);
|
|
||||||
$response->getBody()->write($html);
|
|
||||||
return $response;
|
|
||||||
} else {
|
|
||||||
//if dynamic flag is false, load up html
|
|
||||||
$view = Twig::fromRequest($request);
|
|
||||||
$html = file_get_contents('../public/index.html');
|
|
||||||
$response->getBody()->write($html);
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//if flag is not present, default to static html
|
|
||||||
$view = Twig::fromRequest($request);
|
|
||||||
$html = file_get_contents('../public/index.html');
|
|
||||||
$response->getBody()->write($html);
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
44
brain/controller/RouteControl.inc.php
Normal file
44
brain/controller/RouteControl.inc.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
include "../brain/controller/IndexControl.inc.php";
|
||||||
|
include "../brain/controller/DashControl.inc.php";
|
||||||
|
include "../brain/controller/APIControl.inc.php";
|
||||||
|
|
||||||
|
class RouteControl
|
||||||
|
{
|
||||||
|
public function get(
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
array $args
|
||||||
|
): ResponseInterface {
|
||||||
|
switch (isset($args["first"]) ? $args["first"] : "index") {
|
||||||
|
case "dashboard":
|
||||||
|
return DashControl::start($request, $response, $args);
|
||||||
|
break;
|
||||||
|
case "api":
|
||||||
|
return APIControl::get($request, $response, $args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return IndexControl::start($request, $response, $args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function post(
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
array $args
|
||||||
|
): ResponseInterface {
|
||||||
|
switch (isset($args["first"]) ? $args["first"] : "index") {
|
||||||
|
case "api":
|
||||||
|
return APIControl::post($request, $response, $args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//echo "YES";
|
||||||
|
//return IndexControl::start($request, $response, $args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\controller;
|
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
|
|
||||||
class RouteControl
|
|
||||||
{
|
|
||||||
//TODO: Add additional HTTP Methods to better organize API control paths
|
|
||||||
public function get(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
ResponseInterface $response,
|
|
||||||
array $args
|
|
||||||
): ResponseInterface {
|
|
||||||
switch (isset($args['first']) ? $args['first'] : 'index') {
|
|
||||||
case 'dashboard':
|
|
||||||
return DashControl::start($request, $response, $args);
|
|
||||||
break;
|
|
||||||
case 'api':
|
|
||||||
return APIControl::get($request, $response, $args);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return IndexControl::start($request, $response, $args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function post(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
ResponseInterface $response,
|
|
||||||
array $args
|
|
||||||
): ResponseInterface {
|
|
||||||
switch (isset($args['first']) ? $args['first'] : 'index') {
|
|
||||||
case 'api':
|
|
||||||
return APIControl::post($request, $response, $args);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$result = [
|
|
||||||
'message' => "Nothing matches this route. That's unfortunate",
|
|
||||||
'type' => 'TASK_NONE',
|
|
||||||
];
|
|
||||||
$response->getBody()->write(json_encode($result));
|
|
||||||
return $response->withHeader('Content-Type', 'application/json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
154
brain/data/Auth.inc.php
Normal file
154
brain/data/Auth.inc.php
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use function _\find;
|
||||||
|
use ReallySimpleJWT\Token;
|
||||||
|
|
||||||
|
class Auth
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function sessionStatus()
|
||||||
|
{
|
||||||
|
if (isset($_SESSION["member"])) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//return $this->secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function status()
|
||||||
|
{
|
||||||
|
$result = "";
|
||||||
|
if (Session::active()) {
|
||||||
|
$result = true;
|
||||||
|
} else {
|
||||||
|
$result = false;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function login($who)
|
||||||
|
{
|
||||||
|
//grab member list
|
||||||
|
$folks = (new Settings())->getFolks();
|
||||||
|
$found = find($folks, ["handle" => $who["handle"]]);
|
||||||
|
|
||||||
|
if ($found) {
|
||||||
|
//name is found, verify password
|
||||||
|
if (password_verify($who["password"], $found["password"])) {
|
||||||
|
$member = [
|
||||||
|
"handle" => $found["handle"],
|
||||||
|
"email" => $found["email"],
|
||||||
|
"role" => $found["role"],
|
||||||
|
"avatar" => $found["avi"],
|
||||||
|
"key" => $found["key"],
|
||||||
|
];
|
||||||
|
|
||||||
|
$token = Token::create(
|
||||||
|
$found["key"],
|
||||||
|
$found["secret"],
|
||||||
|
time() + 3600,
|
||||||
|
"localhost"
|
||||||
|
); //expires in an hour
|
||||||
|
|
||||||
|
$form_token = md5(uniqid(microtime(), true));
|
||||||
|
Session::start();
|
||||||
|
Session::set("member", $member);
|
||||||
|
Session::set("token", $token);
|
||||||
|
Session::set("form_token", $form_token);
|
||||||
|
|
||||||
|
$result = "good_login";
|
||||||
|
} else {
|
||||||
|
$result = "bad_pass";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//if name is not found
|
||||||
|
$result = "no_name";
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function findSecret($data)
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
$folks = (new Settings())->getFolks();
|
||||||
|
|
||||||
|
if (
|
||||||
|
!empty($data["email"]) &&
|
||||||
|
filter_var($data["email"], FILTER_VALIDATE_EMAIL)
|
||||||
|
) {
|
||||||
|
$found = find($folks, ["email" => $data["email"]]);
|
||||||
|
if ($found) {
|
||||||
|
//if email is cool, check mail relay status
|
||||||
|
//if set up, send secret there, if not just return it
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$email = $settings["email"]["active"];
|
||||||
|
if ($email != "option-none") {
|
||||||
|
$data["mail_task"] = "SEND_SECRET";
|
||||||
|
$data["secret"] = $found["secret"];
|
||||||
|
$result = Mailer::sendmail($data);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Valid email, but no email set up!",
|
||||||
|
"type" => "secretFound",
|
||||||
|
"secret" => $found["secret"],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "No valid email, no goodies, pleighboi",
|
||||||
|
"type" => "secretNotFound",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Aye, this address is not right, slick.",
|
||||||
|
"type" => "secretNotFound",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function makeNewPassword($data)
|
||||||
|
{
|
||||||
|
//check if passwordsmatch
|
||||||
|
if ($data["newPass"] == $data["newPassConfirm"]) {
|
||||||
|
//verify secret
|
||||||
|
$folks = (new Settings())->getFolks();
|
||||||
|
$found = find($folks, ["secret" => $data["secret"]]);
|
||||||
|
if ($found) {
|
||||||
|
//create new pass and secret key, then update file
|
||||||
|
$hash = password_hash($data["newPass"], PASSWORD_DEFAULT);
|
||||||
|
$freshSecret = StringTools::randomString(12);
|
||||||
|
Member::updateData("password", $hash, $data["secret"]);
|
||||||
|
Member::updateData("secret", $freshSecret, $data["secret"]);
|
||||||
|
$result = [
|
||||||
|
"message" => "Password Updated. Very nice!",
|
||||||
|
"type" => "passCreated",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Secret key is invalid. Try to retrieve it again",
|
||||||
|
"type" => "passNotCreated",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"message" => "Passwords don't match. Try it again.",
|
||||||
|
"type" => "passNotCreated",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function logout()
|
||||||
|
{
|
||||||
|
Session::kill();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,154 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
use ReallySimpleJWT\Token;
|
|
||||||
|
|
||||||
use function _\find;
|
|
||||||
|
|
||||||
class Auth
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function sessionStatus()
|
|
||||||
{
|
|
||||||
if (isset($_SESSION['member'])) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//return $this->secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function status()
|
|
||||||
{
|
|
||||||
$result = '';
|
|
||||||
if (Session::active()) {
|
|
||||||
$result = true;
|
|
||||||
} else {
|
|
||||||
$result = false;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function login($who)
|
|
||||||
{
|
|
||||||
//grab member list
|
|
||||||
$folks = (new Settings())->getFolks();
|
|
||||||
$found = find($folks, ['handle' => $who['handle']]);
|
|
||||||
|
|
||||||
if ($found) {
|
|
||||||
//name is found, verify password
|
|
||||||
if (password_verify($who['password'], $found['password'])) {
|
|
||||||
$member = [
|
|
||||||
'handle' => $found['handle'],
|
|
||||||
'email' => $found['email'],
|
|
||||||
'role' => $found['role'],
|
|
||||||
'avatar' => $found['avi'],
|
|
||||||
'key' => $found['key'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$token = Token::create(
|
|
||||||
$found['key'],
|
|
||||||
$found['secret'],
|
|
||||||
time() + 3600,
|
|
||||||
'localhost'
|
|
||||||
); //expires in an hour
|
|
||||||
|
|
||||||
$form_token = md5(uniqid(microtime(), true));
|
|
||||||
Session::start();
|
|
||||||
Session::set('member', $member);
|
|
||||||
Session::set('token', $token);
|
|
||||||
Session::set('form_token', $form_token);
|
|
||||||
|
|
||||||
$result = 'good_login';
|
|
||||||
} else {
|
|
||||||
$result = 'bad_pass';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//if name is not found
|
|
||||||
$result = 'no_name';
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function findSecret($data)
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
$folks = (new Settings())->getFolks();
|
|
||||||
|
|
||||||
if (!empty($data['email']) && filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
|
|
||||||
$found = find($folks, ['email' => $data['email']]);
|
|
||||||
if ($found) {
|
|
||||||
//if email is cool, check mail relay status
|
|
||||||
//if set up, send secret there, if not just return it
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$email = $settings['email']['active'];
|
|
||||||
if ($email != 'option-none') {
|
|
||||||
$data['mail_task'] = 'SEND_SECRET';
|
|
||||||
$data['secret'] = $found['secret'];
|
|
||||||
$result = Mailer::sendmail($data);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Valid email, but no email set up!',
|
|
||||||
'type' => 'secretFound',
|
|
||||||
'secret' => $found['secret'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'No valid email, no goodies, pleighboi',
|
|
||||||
'type' => 'secretNotFound',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Aye, this address is not right, slick.',
|
|
||||||
'type' => 'secretNotFound',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function makeNewPassword($data)
|
|
||||||
{
|
|
||||||
//check if passwordsmatch
|
|
||||||
if ($data['newPass'] == $data['newPassConfirm']) {
|
|
||||||
//verify secret
|
|
||||||
$folks = (new Settings())->getFolks();
|
|
||||||
$found = find($folks, ['secret' => $data['secret']]);
|
|
||||||
if ($found) {
|
|
||||||
//create new pass and secret key, then update file
|
|
||||||
$hash = password_hash($data['newPass'], PASSWORD_DEFAULT);
|
|
||||||
$freshSecret = StringTools::randomString(12);
|
|
||||||
Member::updateData('password', $hash, $data['secret']);
|
|
||||||
Member::updateData('secret', $freshSecret, $data['secret']);
|
|
||||||
$result = [
|
|
||||||
'message' => 'Password Updated. Very nice!',
|
|
||||||
'type' => 'passCreated',
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => 'Secret key is invalid. Try to retrieve it again',
|
|
||||||
'type' => 'passNotCreated',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'message' => "Passwords don't match. Try it again.",
|
|
||||||
'type' => 'passNotCreated',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function logout()
|
|
||||||
{
|
|
||||||
Session::kill();
|
|
||||||
}
|
|
||||||
}
|
|
322
brain/data/Book.inc.php
Normal file
322
brain/data/Book.inc.php
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Mni\FrontYAML\Parser;
|
||||||
|
use function _\orderBy;
|
||||||
|
use function _\filter;
|
||||||
|
use function _\find;
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
public $files = [];
|
||||||
|
|
||||||
|
public function __construct($folder)
|
||||||
|
{
|
||||||
|
$this->read($folder);
|
||||||
|
}
|
||||||
|
public function read($folder)
|
||||||
|
{
|
||||||
|
$folders = glob("$folder/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($folders as $folder) {
|
||||||
|
//$this->files[] = $folder . "/";
|
||||||
|
$this->read($folder);
|
||||||
|
}
|
||||||
|
$files = array_filter(glob("$folder/*md"), "is_file");
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$this->files[] = $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findPageById(string $uuid)
|
||||||
|
{
|
||||||
|
$content = $this->getContents();
|
||||||
|
$page = find($content, ["uuid" => $uuid]);
|
||||||
|
return $page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findPageBySlug(string $slug = null)
|
||||||
|
{
|
||||||
|
$content = $this->getContents();
|
||||||
|
if (isset($slug)) {
|
||||||
|
$page = find($content, ["slug" => $slug]);
|
||||||
|
} else {
|
||||||
|
$page = find($content, ["layout" => "index"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function editPage($task, $request)
|
||||||
|
{
|
||||||
|
$content = $this->getContents();
|
||||||
|
if ($task == "delete") {
|
||||||
|
$parsed = json_decode(file_get_contents("php://input"), true);
|
||||||
|
$body = find($content, ["uuid" => $parsed["id"]]);
|
||||||
|
} else {
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = find($content, ["uuid" => $body["uuid"]]);
|
||||||
|
$image = $request->getUploadedFiles();
|
||||||
|
$member = Session::get("member");
|
||||||
|
|
||||||
|
if ($task != "create") {
|
||||||
|
$path =
|
||||||
|
date("Y", date($page["rawCreated"])) .
|
||||||
|
"/" .
|
||||||
|
date("m", date($page["rawCreated"]));
|
||||||
|
} else {
|
||||||
|
$path = date("Y") . "/" . date("m");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($image["feature_image"])) {
|
||||||
|
if ($task != "create") {
|
||||||
|
$feature =
|
||||||
|
"/assets/images/blog/" .
|
||||||
|
$path .
|
||||||
|
"/" .
|
||||||
|
$image["feature_image"]->getClientFileName();
|
||||||
|
} else {
|
||||||
|
$feature =
|
||||||
|
"/assets/images/blog/" .
|
||||||
|
$path .
|
||||||
|
"/" .
|
||||||
|
$image["feature_image"]->getClientFileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileUploader::uploadFile(
|
||||||
|
"../public/assets/images/blog/" . $path . "/",
|
||||||
|
$image["feature_image"]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (isset($body["feature_image"])) {
|
||||||
|
$url = explode("/", $body["feature_image"]);
|
||||||
|
$feature =
|
||||||
|
"/" .
|
||||||
|
$url[3] .
|
||||||
|
"/" .
|
||||||
|
$url[4] .
|
||||||
|
"/" .
|
||||||
|
$url[5] .
|
||||||
|
"/" .
|
||||||
|
$url[6] .
|
||||||
|
"/" .
|
||||||
|
$url[7] .
|
||||||
|
"/" .
|
||||||
|
$url[8];
|
||||||
|
} else {
|
||||||
|
$task == "create" ? ($feature = "") : ($feature = $body["feature"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($task == "delete") {
|
||||||
|
$deleted = "true";
|
||||||
|
$body["menu"] ? ($body["menu"] = "true") : ($body["menu"] = "false");
|
||||||
|
$body["published"]
|
||||||
|
? ($body["published"] = "true")
|
||||||
|
: ($body["published"] = "false");
|
||||||
|
$body["featured"]
|
||||||
|
? ($body["featured"] = "true")
|
||||||
|
: ($body["featured"] = "false");
|
||||||
|
} else {
|
||||||
|
$deleted = isset($page["deleted"]) ? $page["deleted"] : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
$created =
|
||||||
|
$task != "create"
|
||||||
|
? new \Moment\Moment($page["rawCreated"])
|
||||||
|
: new \Moment\Moment();
|
||||||
|
$updated = new \Moment\Moment();
|
||||||
|
|
||||||
|
//grab current index from settings and update
|
||||||
|
$id = $task != "create" ? $body["id"] : Settings::getCurrentIndex();
|
||||||
|
$uuid = $task != "create" ? $body["uuid"] : StringTools::createUUID();
|
||||||
|
// now that variables are done, set to body object and then convert to markdown to save
|
||||||
|
|
||||||
|
$body["id"] = $id;
|
||||||
|
$body["uuid"] = $uuid;
|
||||||
|
$body["feature"] = $feature;
|
||||||
|
$body["path"] = $path;
|
||||||
|
$body["author"] = $member["handle"];
|
||||||
|
$body["created"] = $created->format("Y-m-d\TH:i:sP");
|
||||||
|
$body["updated"] = $updated->format("Y-m-d\TH:i:sP");
|
||||||
|
$body["deleted"] = $deleted;
|
||||||
|
|
||||||
|
$write = DocTools::objectToMD($body);
|
||||||
|
|
||||||
|
// if layout is index, change path to file
|
||||||
|
|
||||||
|
if ($body["layout"] == "index") {
|
||||||
|
$writePath = "../content/pages/start/index.md";
|
||||||
|
} else {
|
||||||
|
$writePath = "../content/pages/" . $path . "/" . $body["slug"] . ".md";
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = DocTools::writePages($task, $path, $writePath, $write);
|
||||||
|
|
||||||
|
if ($status) {
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$message = "";
|
||||||
|
|
||||||
|
if (
|
||||||
|
$settings["global"]["renderOnSave"] == "true" &&
|
||||||
|
$settings["global"]["dynamicRender"] == "false"
|
||||||
|
) {
|
||||||
|
$render = new Render();
|
||||||
|
$render->renderTags();
|
||||||
|
$render->renderArchive();
|
||||||
|
$render->renderPages();
|
||||||
|
$message = "Filed edited and rendered. NOICE.";
|
||||||
|
} else {
|
||||||
|
$message = "File edited. Nice work";
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
"message" => $message,
|
||||||
|
"type" => $task == "write" ? "postUpdated" : "postAdded",
|
||||||
|
"id" => $uuid,
|
||||||
|
];
|
||||||
|
|
||||||
|
//TODO: When form submission is successful, make new form token
|
||||||
|
//Session token doesn't reset on the front end, so turning this off for now
|
||||||
|
//$form_token = md5(uniqid(microtime(), true));
|
||||||
|
//Session::set("form_token", $form_token);
|
||||||
|
|
||||||
|
//once saved, update menu
|
||||||
|
$body["path"] = $path;
|
||||||
|
Settings::updateMenu($body);
|
||||||
|
Settings::updateTags();
|
||||||
|
//if new page added, update current index in Settings file
|
||||||
|
if ($task == "create") {
|
||||||
|
Settings::updateIndex();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response = [
|
||||||
|
"message" => "Uh oh. File save problem. Don't panic",
|
||||||
|
"type" => "postError",
|
||||||
|
"id" => $uuid,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPages(int $page, int $limit, string $sort = null)
|
||||||
|
{
|
||||||
|
$content = $this->getContents();
|
||||||
|
|
||||||
|
$published = filter($content, function ($item) {
|
||||||
|
return $item["published"] == true && $item["deleted"] == false;
|
||||||
|
});
|
||||||
|
$deleted = filter($content, function ($item) {
|
||||||
|
return $item["deleted"] == true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$all = $content;
|
||||||
|
$filter = isset($sort) ? $sort : "all";
|
||||||
|
switch ($filter) {
|
||||||
|
case "published":
|
||||||
|
$filtered = $published;
|
||||||
|
break;
|
||||||
|
case "deleted":
|
||||||
|
$filtered = $deleted;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$filtered = $content;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$numOfPages = ceil(count($filtered) / ($limit + 1));
|
||||||
|
$folder = [];
|
||||||
|
|
||||||
|
if (count($filtered) != 0) {
|
||||||
|
if (count($filtered) < $limit) {
|
||||||
|
$limit = count($filtered) - 1;
|
||||||
|
}
|
||||||
|
$range = $page * $limit - $limit;
|
||||||
|
|
||||||
|
if ($range != 0) {
|
||||||
|
$range = $range + 1;
|
||||||
|
}
|
||||||
|
for ($i = 0; $i <= $limit; $i++) {
|
||||||
|
if (isset($filtered[$i + $range])) {
|
||||||
|
array_push($folder, $filtered[$i + $range]);
|
||||||
|
} else {
|
||||||
|
//chill out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$prev = $page - 1;
|
||||||
|
if ($prev <= 0) {
|
||||||
|
$prev = $numOfPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
$next = $page + 1;
|
||||||
|
if ($next > $numOfPages) {
|
||||||
|
$next = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
"pages" => $folder,
|
||||||
|
"numOfPages" => $numOfPages,
|
||||||
|
"entryCount" => count($filtered),
|
||||||
|
"paginate" => [
|
||||||
|
"sort" => $sort,
|
||||||
|
"nextPage" => $next,
|
||||||
|
"prevPage" => $prev,
|
||||||
|
],
|
||||||
|
"stats" => [
|
||||||
|
"all" => count($all),
|
||||||
|
"published" => count($published),
|
||||||
|
"deleted" => count($deleted),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
public function getContents()
|
||||||
|
{
|
||||||
|
//move page collection to utiltiy class
|
||||||
|
$parser = new Parser();
|
||||||
|
$contents = [];
|
||||||
|
foreach ($this->files as $file) {
|
||||||
|
$doc = $parser->parse(file_get_contents($file), false);
|
||||||
|
$meta = $doc->getYAML();
|
||||||
|
$page = [
|
||||||
|
"id" => $meta["id"],
|
||||||
|
"uuid" => $meta["uuid"],
|
||||||
|
"title" => $meta["title"],
|
||||||
|
"feature" => $meta["feature"],
|
||||||
|
"path" => $meta["path"],
|
||||||
|
"layout" => $meta["layout"],
|
||||||
|
"tags" => $meta["tags"],
|
||||||
|
"author" => $meta["author"],
|
||||||
|
"created" => date("Y M D d", $meta["created"]),
|
||||||
|
"updated" => date("Y M D d", $meta["updated"]),
|
||||||
|
"rawCreated" => $meta["created"],
|
||||||
|
"rawUpdated" => $meta["updated"],
|
||||||
|
"createdYear" => date("Y", $meta["created"]),
|
||||||
|
"createdMonth" => date("m", $meta["created"]),
|
||||||
|
"deleted" => $meta["deleted"],
|
||||||
|
"menu" => $meta["menu"],
|
||||||
|
"featured" => $meta["featured"],
|
||||||
|
"published" => $meta["published"],
|
||||||
|
"slug" => $meta["slug"],
|
||||||
|
"filePath" => $file,
|
||||||
|
"content" => $doc->getContent(),
|
||||||
|
];
|
||||||
|
//checks for duplicates
|
||||||
|
$uuid = $meta["uuid"];
|
||||||
|
$found = current(
|
||||||
|
array_filter($contents, function ($item) use ($uuid) {
|
||||||
|
return isset($item["uuid"]) && $uuid == $item["uuid"];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// if uuid is not present, add it
|
||||||
|
if (!$found) {
|
||||||
|
array_push($contents, $page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$contents = orderBy($contents, ["id"], ["desc"]);
|
||||||
|
return $contents;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,230 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use brain\utility\DocTools;
|
|
||||||
use brain\utility\StringTools;
|
|
||||||
|
|
||||||
use function _\find;
|
|
||||||
use function _\filter;
|
|
||||||
|
|
||||||
class Book
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findPageById(string $uuid)
|
|
||||||
{
|
|
||||||
$content = $this->getContents();
|
|
||||||
$page = find($content, ['uuid' => $uuid]);
|
|
||||||
|
|
||||||
return $page;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findPageBySlug(string $slug = null)
|
|
||||||
{
|
|
||||||
$content = $this->getContents();
|
|
||||||
if (isset($slug)) {
|
|
||||||
$page = find($content, ['slug' => $slug]);
|
|
||||||
} else {
|
|
||||||
$page = find($content, ['layout' => 'index']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $page;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function editPage($task, $request)
|
|
||||||
{
|
|
||||||
$content = $this->getContents();
|
|
||||||
$body = json_decode(file_get_contents("php://input"), true);
|
|
||||||
//$body = find($content, ["uuid" => $parsed["id"]]);
|
|
||||||
|
|
||||||
$page = find($content, ['uuid' => $body['uuid']]);
|
|
||||||
$files = $request->getUploadedFiles();
|
|
||||||
|
|
||||||
$member = Session::get('member');
|
|
||||||
|
|
||||||
if ($task != 'create') {
|
|
||||||
$path = date('Y', date($page['rawCreated'])) .
|
|
||||||
'/' .
|
|
||||||
date('m', date($page['rawCreated']));
|
|
||||||
} else {
|
|
||||||
$path = date('Y') . '/' . date('m');
|
|
||||||
}
|
|
||||||
|
|
||||||
$page_feature = '';
|
|
||||||
$page_files = '';
|
|
||||||
|
|
||||||
if ($task == 'delete') {
|
|
||||||
$deleted = 'true';
|
|
||||||
$body['menu'] = 'false';
|
|
||||||
$body['published'] = 'false';
|
|
||||||
$body['featured'] = 'false';
|
|
||||||
} else {
|
|
||||||
$deleted = isset($page['deleted']) ? $page['deleted'] : 'false';
|
|
||||||
}
|
|
||||||
|
|
||||||
$created = $task != 'create' ? new Carbon($page['rawCreated']) : Carbon::now();
|
|
||||||
$updated = Carbon::now();
|
|
||||||
|
|
||||||
// grab current index from settings and update
|
|
||||||
$id = $task != 'create' ? $body['id'] : Settings::getCurrentIndex();
|
|
||||||
$uuid = $task != 'create' ? $body['uuid'] : StringTools::createUUID();
|
|
||||||
// now that variables are done, set to body object and then convert to markdown to save
|
|
||||||
|
|
||||||
$body['id'] = $id;
|
|
||||||
$body['uuid'] = $uuid;
|
|
||||||
//$body['feature'] = $page_feature;
|
|
||||||
//$body['files'] = $page_files;
|
|
||||||
$body['path'] = $path;
|
|
||||||
$body['author'] = $member['handle'];
|
|
||||||
$body['created'] = $created->format("Y-m-d\TH:i:sP");
|
|
||||||
$body['updated'] = $updated->format("Y-m-d\TH:i:sP");
|
|
||||||
$body['deleted'] = $deleted;
|
|
||||||
|
|
||||||
$write = DocTools::objectToMD($body);
|
|
||||||
|
|
||||||
// if layout is index, change path to file
|
|
||||||
|
|
||||||
if ($body['layout'] == 'index') {
|
|
||||||
$writePath = '../content/pages/start/index.md';
|
|
||||||
} else {
|
|
||||||
$writePath = '../content/pages/' . $path . '/' . $body['slug'] . '.md';
|
|
||||||
}
|
|
||||||
|
|
||||||
$status = DocTools::writePages($task, $path, $writePath, $write);
|
|
||||||
|
|
||||||
if ($status) {
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$message = '';
|
|
||||||
|
|
||||||
if (
|
|
||||||
$settings['global']['renderOnSave'] == 'true' &&
|
|
||||||
$settings['global']['dynamicRender'] == 'false'
|
|
||||||
) {
|
|
||||||
$render = new Render();
|
|
||||||
$render->renderTags();
|
|
||||||
$render->renderArchive();
|
|
||||||
$render->renderPages();
|
|
||||||
$message = 'Filed edited and rendered. NOICE.';
|
|
||||||
} else {
|
|
||||||
$message = 'File edited. Nice work';
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = [
|
|
||||||
'message' => $message,
|
|
||||||
'type' => $task == 'write' ? 'postUpdated' : 'postAdded',
|
|
||||||
'id' => $uuid,
|
|
||||||
];
|
|
||||||
|
|
||||||
// TODO: When form submission is successful, make new form token
|
|
||||||
// Session token doesn't reset on the front end, so turning this off for now
|
|
||||||
// $form_token = md5(uniqid(microtime(), true));
|
|
||||||
// Session::set("form_token", $form_token);
|
|
||||||
|
|
||||||
// once saved, update menu
|
|
||||||
$body['path'] = $path;
|
|
||||||
Settings::updateMenu($body);
|
|
||||||
Settings::updateTags();
|
|
||||||
// if new page added, update current index in Settings file
|
|
||||||
if ($task == 'create') {
|
|
||||||
Settings::updateIndex();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$response = [
|
|
||||||
'message' => "Uh oh. File save problem. Don't panic",
|
|
||||||
'type' => 'postError',
|
|
||||||
'id' => $uuid,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPages(int $page, int $limit, string $sort = null)
|
|
||||||
{
|
|
||||||
$content = $this->getContents();
|
|
||||||
|
|
||||||
$published = filter($content, function ($item) {
|
|
||||||
return $item['published'] == true && $item['deleted'] == false;
|
|
||||||
});
|
|
||||||
$deleted = filter($content, function ($item) {
|
|
||||||
return $item['deleted'] == true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// $all = $content;
|
|
||||||
$all = filter($content, function ($item) {
|
|
||||||
return $item['deleted'] == false;
|
|
||||||
});
|
|
||||||
$filter = isset($sort) ? $sort : 'all';
|
|
||||||
switch ($filter) {
|
|
||||||
case 'published':
|
|
||||||
$filtered = $published;
|
|
||||||
break;
|
|
||||||
case 'deleted':
|
|
||||||
$filtered = $deleted;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$filtered = $all;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$numOfPages = ceil(count($filtered) / ($limit + 1));
|
|
||||||
$folder = [];
|
|
||||||
|
|
||||||
if (count($filtered) != 0) {
|
|
||||||
if (count($filtered) < $limit) {
|
|
||||||
$limit = count($filtered) - 1;
|
|
||||||
}
|
|
||||||
$range = $page * $limit - $limit;
|
|
||||||
|
|
||||||
if ($range != 0) {
|
|
||||||
$range = $range + 1;
|
|
||||||
}
|
|
||||||
for ($i = 0; $i <= $limit; ++$i) {
|
|
||||||
if (isset($filtered[$i + $range])) {
|
|
||||||
array_push($folder, $filtered[$i + $range]);
|
|
||||||
} else {
|
|
||||||
// chill out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$prev = $page - 1;
|
|
||||||
if ($prev <= 0) {
|
|
||||||
$prev = $numOfPages;
|
|
||||||
}
|
|
||||||
|
|
||||||
$next = $page + 1;
|
|
||||||
if ($next > $numOfPages) {
|
|
||||||
$next = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'pages' => $folder,
|
|
||||||
'numOfPages' => $numOfPages,
|
|
||||||
'entryCount' => count($filtered),
|
|
||||||
'paginate' => [
|
|
||||||
'sort' => $sort,
|
|
||||||
'nextPage' => $next,
|
|
||||||
'prevPage' => $prev,
|
|
||||||
],
|
|
||||||
'stats' => [
|
|
||||||
'all' => count($all),
|
|
||||||
'published' => count($published),
|
|
||||||
'deleted' => count($deleted),
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getContents()
|
|
||||||
{
|
|
||||||
// test new contents data class
|
|
||||||
// $new = (new Contents("../content/pages"))->getAll();
|
|
||||||
$contents = (new Contents('../content/pages'))->getAll();
|
|
||||||
|
|
||||||
return $contents;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,193 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
use HtmlSanitizer\SanitizerBuilder;
|
|
||||||
use League\CommonMark\MarkdownConverter;
|
|
||||||
use League\CommonMark\Environment\Environment;
|
|
||||||
use HtmlSanitizer\Extension\Basic\BasicExtension;
|
|
||||||
use HtmlSanitizer\Extension\Listing\ListExtension;
|
|
||||||
use HtmlSanitizer\Extension\Iframe\IframeExtension;
|
|
||||||
use League\CommonMark\Extension\Table\TableExtension;
|
|
||||||
use League\CommonMark\Extension\Attributes\AttributesExtension;
|
|
||||||
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
|
|
||||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
|
||||||
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
|
|
||||||
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
|
|
||||||
|
|
||||||
use function _\orderBy;
|
|
||||||
|
|
||||||
class Contents
|
|
||||||
{
|
|
||||||
public $files = [];
|
|
||||||
public $config = [];
|
|
||||||
|
|
||||||
public function __construct($folder)
|
|
||||||
{
|
|
||||||
$this->read($folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function read($folder)
|
|
||||||
{
|
|
||||||
$folders = glob("$folder/*", GLOB_ONLYDIR);
|
|
||||||
foreach ($folders as $folder) {
|
|
||||||
//$this->files[] = $folder . "/";
|
|
||||||
$this->read($folder);
|
|
||||||
}
|
|
||||||
$files = array_filter(glob("$folder/*md"), 'is_file');
|
|
||||||
foreach ($files as $file) {
|
|
||||||
$this->files[] = $file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAll()
|
|
||||||
{
|
|
||||||
$environment = new Environment($this->config);
|
|
||||||
$environment->addExtension(new CommonMarkCoreExtension());
|
|
||||||
|
|
||||||
// Add the extension
|
|
||||||
$environment->addExtension(new FrontMatterExtension());
|
|
||||||
|
|
||||||
//Add Strikethrough rendering
|
|
||||||
$environment->addExtension(new StrikethroughExtension());
|
|
||||||
|
|
||||||
//add attributes to elements in markdown
|
|
||||||
$environment->addExtension(new AttributesExtension());
|
|
||||||
|
|
||||||
//add table rendering
|
|
||||||
$environment->addExtension(new TableExtension());
|
|
||||||
|
|
||||||
// Instantiate the converter engine and start converting some Markdown!
|
|
||||||
$converter = new MarkdownConverter($environment);
|
|
||||||
|
|
||||||
$contents = [];
|
|
||||||
foreach ($this->files as $file) {
|
|
||||||
//get meta and html from file
|
|
||||||
$result = $converter->convertToHtml(file_get_contents($file));
|
|
||||||
$meta = [];
|
|
||||||
if ($result instanceof RenderedContentWithFrontMatter) {
|
|
||||||
$meta = $result->getFrontMatter();
|
|
||||||
}
|
|
||||||
|
|
||||||
//get raw markdown from file
|
|
||||||
$frontMatterExtension = new FrontMatterExtension();
|
|
||||||
$parsed = $frontMatterExtension
|
|
||||||
->getFrontMatterParser()
|
|
||||||
->parse(file_get_contents($file));
|
|
||||||
|
|
||||||
//never trust the front end. clean it up
|
|
||||||
//add what sanitizer extensions we need manually
|
|
||||||
$builder = new SanitizerBuilder();
|
|
||||||
$builder->registerExtension(new BasicExtension());
|
|
||||||
$builder->registerExtension(new IframeExtension());
|
|
||||||
$builder->registerExtension(new ListExtension());
|
|
||||||
//just add it straight because classname is already in use
|
|
||||||
$builder->registerExtension(new \HtmlSanitizer\Extension\Table\TableExtension());
|
|
||||||
|
|
||||||
//relative-a and relative-image
|
|
||||||
$builder->registerExtension(
|
|
||||||
new \HtmlSanitizer\Extension\Relative\A\AExtension()
|
|
||||||
);
|
|
||||||
$builder->registerExtension(
|
|
||||||
new \HtmlSanitizer\Extension\Relative\Image\ImageExtension()
|
|
||||||
);
|
|
||||||
|
|
||||||
$detergent = [
|
|
||||||
'extensions' => ['basic', 'list', 'relative-a', 'relative-image', 'iframe', 'table'],
|
|
||||||
'tags' => [
|
|
||||||
'div' => [
|
|
||||||
'allowed_attributes' => ['class', 'title', 'id', 'style'],
|
|
||||||
],
|
|
||||||
'img' => [
|
|
||||||
'allowed_attributes' => ['src', 'alt', 'title', 'class'],
|
|
||||||
],
|
|
||||||
'iframe' => [
|
|
||||||
'allowed_attributes' => ['height', 'width', 'title', 'src'],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$sanitizer = $builder->build($detergent);
|
|
||||||
$scrubbed = $sanitizer->sanitize($result->getContent());
|
|
||||||
if (isset($meta['feature'])) {
|
|
||||||
$featureList = explode(',', $meta['feature']);
|
|
||||||
} else {
|
|
||||||
$featureList = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
$docs = '';
|
|
||||||
if (isset($meta['files'])) {
|
|
||||||
$fileList = explode(',', $meta['files']);
|
|
||||||
$docs = $meta['files'];
|
|
||||||
} else {
|
|
||||||
$fileList = [];
|
|
||||||
$docs = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$media = [];
|
|
||||||
$files = [];
|
|
||||||
if ($featureList != '') {
|
|
||||||
foreach ($featureList as $file) {
|
|
||||||
$item = trim($file);
|
|
||||||
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
|
||||||
if ($item != null || $item != '') {
|
|
||||||
array_push($media, ['file' => $item, 'type' => trim($ext)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($fileList != "") {
|
|
||||||
foreach ($fileList as $file) {
|
|
||||||
$item = trim($file);
|
|
||||||
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
|
||||||
if ($item != null || $item != '') {
|
|
||||||
array_push($files, ['file' => $item, 'type' => trim($ext)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//sort attributes into page object
|
|
||||||
$page = [
|
|
||||||
'id' => $meta['id'],
|
|
||||||
'uuid' => $meta['uuid'],
|
|
||||||
'title' => $meta['title'],
|
|
||||||
'feature' => $meta['feature'],
|
|
||||||
'files' => $docs,
|
|
||||||
'path' => $meta['path'],
|
|
||||||
'layout' => $meta['layout'],
|
|
||||||
'tags' => $meta['tags'],
|
|
||||||
'author' => $meta['author'],
|
|
||||||
'created' => date('Y M D d', $meta['created']),
|
|
||||||
'updated' => date('Y M D d', $meta['updated']),
|
|
||||||
'rawCreated' => $meta['created'],
|
|
||||||
'rawUpdated' => $meta['updated'],
|
|
||||||
'createdYear' => date('Y', $meta['created']),
|
|
||||||
'createdMonth' => date('m', $meta['created']),
|
|
||||||
'deleted' => $meta['deleted'],
|
|
||||||
'menu' => $meta['menu'],
|
|
||||||
'featured' => $meta['featured'],
|
|
||||||
'published' => $meta['published'],
|
|
||||||
'slug' => $meta['slug'],
|
|
||||||
'filePath' => $file,
|
|
||||||
'content' => $parsed->getContent(),
|
|
||||||
'html' => $scrubbed,
|
|
||||||
'media' => $media,
|
|
||||||
'docs' => $files
|
|
||||||
];
|
|
||||||
//checks for duplicates
|
|
||||||
$uuid = $meta['uuid'];
|
|
||||||
$found = current(
|
|
||||||
array_filter($contents, function ($item) use ($uuid) {
|
|
||||||
return isset($item['uuid']) && $uuid == $item['uuid'];
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// if uuid is not present, add it
|
|
||||||
if (!$found) {
|
|
||||||
array_push($contents, $page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$contents = orderBy($contents, ['id'], ['desc']);
|
|
||||||
return $contents;
|
|
||||||
}
|
|
||||||
}
|
|
55
brain/data/Member.inc.php
Normal file
55
brain/data/Member.inc.php
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
use function _\find;
|
||||||
|
|
||||||
|
class Member
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function verifyKey(string $key)
|
||||||
|
{
|
||||||
|
if (isset($key)) {
|
||||||
|
$folks = (new Settings())->getFolks();
|
||||||
|
$found = find($folks, ["key" => $key]);
|
||||||
|
if ($found) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function updateData(string $key, string $data, $secret = null)
|
||||||
|
{
|
||||||
|
$folks = (new Settings())->getFolks();
|
||||||
|
if (isset($secret)) {
|
||||||
|
$found = find($folks, ["secret" => $secret]);
|
||||||
|
} else {
|
||||||
|
$member = Session::get("member");
|
||||||
|
$found = find($folks, ["handle" => $member["handle"]]);
|
||||||
|
}
|
||||||
|
$found[$key] = $data;
|
||||||
|
//record time updated
|
||||||
|
$updated = new \Moment\Moment();
|
||||||
|
$found["updated"] = $updated->format("Y-m-d\TH:i:sP");
|
||||||
|
$newFolks = [];
|
||||||
|
array_push($newFolks, $found);
|
||||||
|
//save updated file
|
||||||
|
DocTools::writeSettings("../config/folks.json", $newFolks);
|
||||||
|
//update member data in session
|
||||||
|
|
||||||
|
if (!isset($secret)) {
|
||||||
|
$member = [
|
||||||
|
"handle" => $found["handle"],
|
||||||
|
"email" => $found["email"],
|
||||||
|
"role" => $found["role"],
|
||||||
|
"avatar" => $found["avi"],
|
||||||
|
"key" => $found["key"],
|
||||||
|
];
|
||||||
|
Session::set("member", $member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use brain\utility\DocTools;
|
|
||||||
|
|
||||||
use function _\find;
|
|
||||||
|
|
||||||
class Member
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function verifyKey(string $key)
|
|
||||||
{
|
|
||||||
if (isset($key)) {
|
|
||||||
$folks = (new Settings())->getFolks();
|
|
||||||
$found = find($folks, ['key' => $key]);
|
|
||||||
if ($found) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function updateData(string $key, string $data, $secret = null)
|
|
||||||
{
|
|
||||||
$folks = (new Settings())->getFolks();
|
|
||||||
if (isset($secret)) {
|
|
||||||
$found = find($folks, ['secret' => $secret]);
|
|
||||||
} else {
|
|
||||||
$member = Session::get('member');
|
|
||||||
$found = find($folks, ['handle' => $member['handle']]);
|
|
||||||
}
|
|
||||||
$found[$key] = $data;
|
|
||||||
//record time updated
|
|
||||||
$updated = Carbon::now();
|
|
||||||
$found['updated'] = $updated->format("Y-m-d\TH:i:sP");
|
|
||||||
$newFolks = [];
|
|
||||||
array_push($newFolks, $found);
|
|
||||||
//save updated file
|
|
||||||
DocTools::writeSettings('../config/folks.json', $newFolks);
|
|
||||||
//update member data in session
|
|
||||||
|
|
||||||
if (!isset($secret)) {
|
|
||||||
$member = [
|
|
||||||
'handle' => $found['handle'],
|
|
||||||
'email' => $found['email'],
|
|
||||||
'role' => $found['role'],
|
|
||||||
'avatar' => $found['avi'],
|
|
||||||
'key' => $found['key'],
|
|
||||||
];
|
|
||||||
Session::set('member', $member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
268
brain/data/Render.inc.php
Normal file
268
brain/data/Render.inc.php
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
<?php
|
||||||
|
use Mni\FrontYAML\Parser;
|
||||||
|
use function _\find;
|
||||||
|
|
||||||
|
class Render
|
||||||
|
{
|
||||||
|
public $loader;
|
||||||
|
public $twig;
|
||||||
|
public $pageInfo;
|
||||||
|
public $menu;
|
||||||
|
public $background;
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$config = new Settings();
|
||||||
|
$this->loader = new \Twig\Loader\FilesystemLoader("../content/themes");
|
||||||
|
$this->twig = new \Twig\Environment($this->loader, []);
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$this->menu = $settings["menu"];
|
||||||
|
$this->theme = $settings["global"]["theme"];
|
||||||
|
$this->pageInfo = [
|
||||||
|
"keywords" => isset($settings["global"]["keywords"])
|
||||||
|
? $settings["global"]["keywords"]
|
||||||
|
: "fipamo, blog, jamstack, php, markdown, js",
|
||||||
|
"description" => $settings["global"]["descriptions"],
|
||||||
|
"image" =>
|
||||||
|
$settings["global"]["base_url"] . $settings["global"]["background"],
|
||||||
|
"baseURL" => $settings["global"]["base_url"],
|
||||||
|
];
|
||||||
|
//move global theme image assets to public folder
|
||||||
|
foreach (
|
||||||
|
new DirectoryIterator(
|
||||||
|
"../content/themes/" . $this->theme . "/assets/images/global/"
|
||||||
|
)
|
||||||
|
as $file
|
||||||
|
) {
|
||||||
|
if ($file->isDot()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!is_file("../public/assets/images/global/" . $file->getFileName())) {
|
||||||
|
copy(
|
||||||
|
"../content/themes/" .
|
||||||
|
$this->theme .
|
||||||
|
"/assets/images/global/" .
|
||||||
|
$file->getFileName(),
|
||||||
|
"../public/assets/images/global/" . $file->getFileName()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
//image is already there, so chill
|
||||||
|
}
|
||||||
|
//print $file->getFilename() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
//copy current theme assets to public
|
||||||
|
if (is_file("../public/assets/css/base.css")) {
|
||||||
|
unlink("../public/assets/css/base.css");
|
||||||
|
}
|
||||||
|
copy(
|
||||||
|
"../content/themes/" . $this->theme . "/assets/css/base.css",
|
||||||
|
"../public/assets/css/base.css"
|
||||||
|
);
|
||||||
|
if (is_file("../public/assets/scripts/start.min.js")) {
|
||||||
|
unlink("../public/assets/scripts/start.min.js");
|
||||||
|
}
|
||||||
|
copy(
|
||||||
|
"../content/themes/" . $this->theme . "/assets/scripts/start.min.js",
|
||||||
|
"../public/assets/scripts/start.min.js"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderPages()
|
||||||
|
{
|
||||||
|
$pages = (new Book("../content/pages"))->getContents();
|
||||||
|
$recent = [];
|
||||||
|
$featured = [];
|
||||||
|
$limit = 4;
|
||||||
|
foreach ($pages as $page) {
|
||||||
|
//TODO: Move page data organization to render to utility class
|
||||||
|
if (!$page["deleted"] && $page["published"]) {
|
||||||
|
if (count($recent) < $limit) {
|
||||||
|
array_push($recent, [
|
||||||
|
"path" => $page["path"],
|
||||||
|
"slug" => $page["slug"],
|
||||||
|
"title" => $page["title"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($page["featured"] == true) {
|
||||||
|
if (count($featured) < $limit) {
|
||||||
|
array_push($featured, [
|
||||||
|
"path" => $page["path"],
|
||||||
|
"slug" => $page["slug"],
|
||||||
|
"title" => $page["title"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$taglist = explode(",", $page["tags"]);
|
||||||
|
$tags = [];
|
||||||
|
foreach ($taglist as $tag) {
|
||||||
|
$label = trim($tag);
|
||||||
|
array_push($tags, [
|
||||||
|
"label" => $label . " ",
|
||||||
|
"slug" => StringTools::safeString($label),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$meta = [
|
||||||
|
"who" => $page["author"],
|
||||||
|
"when" => $page["created"],
|
||||||
|
"tags" => $tags,
|
||||||
|
];
|
||||||
|
|
||||||
|
//render markdown content and clean it
|
||||||
|
$parser = new Parser();
|
||||||
|
$rendered = $parser->parse($page["content"]);
|
||||||
|
$sanitizer = HtmlSanitizer\Sanitizer::create([
|
||||||
|
"extensions" => ["basic", "image", "list", "code"],
|
||||||
|
"tags" => [
|
||||||
|
"img" => [
|
||||||
|
"allowed_attributes" => ["src", "alt", "title", "class"],
|
||||||
|
"allowed_hosts" => null,
|
||||||
|
"allow_relative_links" => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$scrubbed = $sanitizer->sanitize($rendered->getContent());
|
||||||
|
|
||||||
|
//var_dump($scrubbed);
|
||||||
|
|
||||||
|
//just clean renderd string for now, Sanitize doesn't like relative img urls
|
||||||
|
//so another option is needed
|
||||||
|
$cleaned = strip_tags($rendered->getContent(), [
|
||||||
|
"a",
|
||||||
|
"br",
|
||||||
|
"p",
|
||||||
|
"strong",
|
||||||
|
"br",
|
||||||
|
"img",
|
||||||
|
"iframe",
|
||||||
|
"ul",
|
||||||
|
"li",
|
||||||
|
"i",
|
||||||
|
"em",
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"pre",
|
||||||
|
"code",
|
||||||
|
]);
|
||||||
|
//$cleaned = preg_replace('/(?:\r\n|[\r\n]){2,}/', "\n\n", $cleaned);
|
||||||
|
//$cleaned = html_entity_decode($cleaned, ENT_QUOTES, "UTF-8");
|
||||||
|
|
||||||
|
//if page feature isn't empty, replace page info meta image
|
||||||
|
if ($page["feature"] != "" || $page["feature"] != null) {
|
||||||
|
$this->pageInfo["image"] =
|
||||||
|
$this->pageInfo["baseURL"] . $page["feature"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($page["layout"] == "index") {
|
||||||
|
$template = $this->theme . "/index.twig";
|
||||||
|
$location = "../public/index.html";
|
||||||
|
$dir = null;
|
||||||
|
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => $page["title"],
|
||||||
|
"background" => $page["feature"],
|
||||||
|
"content" => $scrubbed,
|
||||||
|
"meta" => $meta,
|
||||||
|
"recent" => $recent,
|
||||||
|
"featured" => $featured,
|
||||||
|
"info" => $this->pageInfo,
|
||||||
|
"menu" => $this->menu,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$template = $this->theme . "/" . $page["layout"] . ".twig";
|
||||||
|
$location =
|
||||||
|
"../public/" . $page["path"] . "/" . $page["slug"] . ".html";
|
||||||
|
$dir = "../public/" . $page["path"];
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => $page["title"],
|
||||||
|
"background" => $page["feature"],
|
||||||
|
"content" => $cleaned,
|
||||||
|
"meta" => $meta,
|
||||||
|
"info" => $this->pageInfo,
|
||||||
|
"menu" => $this->menu,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = $this->twig->render($template, $pageOptions);
|
||||||
|
DocTools::writeHTML($location, $html, $dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderArchive()
|
||||||
|
{
|
||||||
|
$archive = Sorting::archive();
|
||||||
|
$template = $this->theme . "/archive.twig";
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Archive",
|
||||||
|
"background" => $this->pageInfo["image"],
|
||||||
|
"archives" => $archive,
|
||||||
|
"info" => $this->pageInfo,
|
||||||
|
"menu" => $this->menu,
|
||||||
|
];
|
||||||
|
|
||||||
|
$html = $this->twig->render($template, $pageOptions);
|
||||||
|
$location = "../public/archives.html";
|
||||||
|
DocTools::writeHTML($location, $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderTags()
|
||||||
|
{
|
||||||
|
$list = Sorting::tags();
|
||||||
|
foreach ($list as $item) {
|
||||||
|
$template = $this->theme . "/tags.twig";
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Pages Tagged as " . $item["tag_name"],
|
||||||
|
"background" => $this->pageInfo["image"],
|
||||||
|
"tag_list" => $item["pages"],
|
||||||
|
"info" => $this->pageInfo,
|
||||||
|
"menu" => $this->menu,
|
||||||
|
];
|
||||||
|
|
||||||
|
$html = $this->twig->render($template, $pageOptions);
|
||||||
|
|
||||||
|
$location = "../public/tags/" . $item["slug"] . ".html";
|
||||||
|
|
||||||
|
//if tags folder doesn't exist, make it
|
||||||
|
if (!is_dir("../public/tags")) {
|
||||||
|
mkdir("../public/tags", 0755, true);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_file($location)) {
|
||||||
|
file_put_contents($location, $html);
|
||||||
|
} else {
|
||||||
|
($new = fopen($location, "w")) or die("Unable to open file!");
|
||||||
|
fwrite($new, $html);
|
||||||
|
fclose($new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderIndex()
|
||||||
|
{
|
||||||
|
$pages = (new Book("../content/pages"))->getContents();
|
||||||
|
$index = find($pages, ["layout" => "index"]);
|
||||||
|
$template = $this->theme . "/index.twig";
|
||||||
|
$location = "../public/index.html";
|
||||||
|
$dir = null;
|
||||||
|
|
||||||
|
$meta = [
|
||||||
|
"who" => $index["author"],
|
||||||
|
"when" => $index["created"],
|
||||||
|
];
|
||||||
|
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => $index["title"],
|
||||||
|
"background" => $index["feature"],
|
||||||
|
"meta" => $meta,
|
||||||
|
];
|
||||||
|
|
||||||
|
$html = $this->twig->render($template, $pageOptions);
|
||||||
|
DocTools::writeHTML($location, $html, $dir);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,204 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
use brain\utility\Sorting;
|
|
||||||
use brain\utility\DocTools;
|
|
||||||
|
|
||||||
use function _\find;
|
|
||||||
|
|
||||||
class Render
|
|
||||||
{
|
|
||||||
public $loader;
|
|
||||||
public $twig;
|
|
||||||
public $pageInfo;
|
|
||||||
public $menu;
|
|
||||||
public $background;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$config = new Settings();
|
|
||||||
//TODO: Add theme folder to loader
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$this->menu = $settings['menu'];
|
|
||||||
$this->theme = $settings['global']['theme'];
|
|
||||||
$this->loader = new \Twig\Loader\FilesystemLoader('../content/themes/' . $this->theme);
|
|
||||||
$this->twig = new \Twig\Environment($this->loader, []);
|
|
||||||
$this->pageInfo = [
|
|
||||||
'keywords' => isset($settings['global']['keywords'])
|
|
||||||
? $settings['global']['keywords']
|
|
||||||
: 'fipamo, blog, jamstack, php, markdown, js',
|
|
||||||
'description' => $settings['global']['descriptions'],
|
|
||||||
'image' => $settings['global']['base_url'] . $settings['global']['background'],
|
|
||||||
'baseURL' => $settings['global']['base_url'],
|
|
||||||
];
|
|
||||||
//move global theme image assets to public folder
|
|
||||||
foreach (
|
|
||||||
new \DirectoryIterator('../content/themes/' . $this->theme . '/assets/images/global/') as $file
|
|
||||||
) {
|
|
||||||
if ($file->isDot()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!is_file('../public/assets/images/global/' . $file->getFileName())) {
|
|
||||||
copy(
|
|
||||||
'../content/themes/' .
|
|
||||||
$this->theme .
|
|
||||||
'/assets/images/global/' .
|
|
||||||
$file->getFileName(),
|
|
||||||
'../public/assets/images/global/' . $file->getFileName()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
//image is already there, so chill
|
|
||||||
}
|
|
||||||
//print $file->getFilename() . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy current theme assets to public
|
|
||||||
|
|
||||||
//clear files in css and scripts folder
|
|
||||||
$styles = glob('../public/assets/css/*'); // get all file names
|
|
||||||
foreach ($styles as $file) { // iterate files
|
|
||||||
if (is_file($file)) {
|
|
||||||
//don't erase dashboard css
|
|
||||||
if (!$file == '../public/assets/css/dash.css') {
|
|
||||||
unlink($file); // delete file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$scripts = glob('../public/assets/scripts/*'); // get all file names
|
|
||||||
foreach ($scripts as $file) { // iterate files
|
|
||||||
if (is_file($file)) {
|
|
||||||
if (!$file == '../public/assets/scripts/Start.js') {
|
|
||||||
unlink($file); // delete file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//copy theme assets to public
|
|
||||||
$newcss = glob('../content/themes/' . $this->theme . '/assets/css/*');
|
|
||||||
foreach ($newcss as $file) { // iterate files
|
|
||||||
if (is_file($file)) {
|
|
||||||
$path = explode('/', $file);
|
|
||||||
copy($file, '../public/assets/css/' . $path[6]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$newjs = glob('../content/themes/' . $this->theme . '/assets/scripts/*');
|
|
||||||
foreach ($newjs as $file) { // iterate files
|
|
||||||
if (is_file($file)) {
|
|
||||||
$path = explode('/', $file);
|
|
||||||
copy($file, '../public/assets/scripts/' . $path[6]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function renderPages()
|
|
||||||
{
|
|
||||||
$pages = (new Book())->getContents();
|
|
||||||
$recent = [];
|
|
||||||
$featured = [];
|
|
||||||
$limit = 4;
|
|
||||||
foreach ($pages as $page) {
|
|
||||||
$pageOptions = Sorting::page($page);
|
|
||||||
|
|
||||||
$layout = $page['layout'];
|
|
||||||
//new pages have no layout, so defautl for now
|
|
||||||
if ($layout == '' || $layout == null) {
|
|
||||||
$layout = 'page';
|
|
||||||
}
|
|
||||||
|
|
||||||
$template = $layout . '.twig';
|
|
||||||
if (str_contains($layout, 'index')) {
|
|
||||||
$location = '../public/index.html';
|
|
||||||
$dir = null;
|
|
||||||
} else {
|
|
||||||
// if page is a menu item, render the page on public root
|
|
||||||
if ($page['menu'] == 'true') {
|
|
||||||
$location = '../public/' . $page['slug'] . '.html';
|
|
||||||
$dir = '../public/';
|
|
||||||
} else {
|
|
||||||
$location = '../public/' . $page['path'] . '/' . $page['slug'] . '.html';
|
|
||||||
$dir = '../public/' . $page['path'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$html = $this->twig->render($template, $pageOptions);
|
|
||||||
DocTools::writeHTML($location, $html, $dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function renderArchive()
|
|
||||||
{
|
|
||||||
$archive = Sorting::archive();
|
|
||||||
$template = 'archive.twig';
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Archive',
|
|
||||||
'background' => $this->pageInfo['image'],
|
|
||||||
'archives' => $archive,
|
|
||||||
'info' => $this->pageInfo,
|
|
||||||
'menu' => $this->menu,
|
|
||||||
'media' => [['file' => $this->pageInfo['image'], 'type' => trim(pathinfo($this->pageInfo['image'], PATHINFO_EXTENSION))]],
|
|
||||||
];
|
|
||||||
|
|
||||||
$html = $this->twig->render($template, $pageOptions);
|
|
||||||
$location = '../public/archives.html';
|
|
||||||
DocTools::writeHTML($location, $html);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function renderTags()
|
|
||||||
{
|
|
||||||
$list = Sorting::tags();
|
|
||||||
foreach ($list as $item) {
|
|
||||||
$template = 'tags.twig';
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => 'Pages Tagged as ' . $item['tag_name'],
|
|
||||||
'background' => $this->pageInfo['image'],
|
|
||||||
'tag_list' => $item['pages'],
|
|
||||||
'info' => $this->pageInfo,
|
|
||||||
'menu' => $this->menu,
|
|
||||||
'media' => [['file' => $this->pageInfo['image'], 'type' => trim(pathinfo($this->pageInfo['image'], PATHINFO_EXTENSION))]],
|
|
||||||
];
|
|
||||||
|
|
||||||
$html = $this->twig->render($template, $pageOptions);
|
|
||||||
|
|
||||||
$location = '../public/tags/' . $item['slug'] . '.html';
|
|
||||||
|
|
||||||
//if tags folder doesn't exist, make it
|
|
||||||
if (!is_dir('../public/tags')) {
|
|
||||||
mkdir('../public/tags', 0755, true);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_file($location)) {
|
|
||||||
file_put_contents($location, $html);
|
|
||||||
} else {
|
|
||||||
($new = fopen($location, 'w')) or die('Unable to open file!');
|
|
||||||
fwrite($new, $html);
|
|
||||||
fclose($new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function renderIndex()
|
|
||||||
{
|
|
||||||
//TODO: Need to fix this to account for new index templating system
|
|
||||||
$pages = (new Book())->getContents();
|
|
||||||
$index = find($pages, ['layout' => 'index']);
|
|
||||||
$template = 'index.twig';
|
|
||||||
$location = '../public/index.html';
|
|
||||||
$dir = null;
|
|
||||||
|
|
||||||
$meta = [
|
|
||||||
'who' => $index['author'],
|
|
||||||
'when' => $index['created'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => $index['title'],
|
|
||||||
'background' => $index['feature'],
|
|
||||||
'meta' => $meta,
|
|
||||||
];
|
|
||||||
|
|
||||||
$html = $this->twig->render($template, $pageOptions);
|
|
||||||
DocTools::writeHTML($location, $html, $dir);
|
|
||||||
}
|
|
||||||
}
|
|
90
brain/data/Session.inc.php
Normal file
90
brain/data/Session.inc.php
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
use function _\find;
|
||||||
|
use ReallySimpleJWT\Token;
|
||||||
|
|
||||||
|
class Session
|
||||||
|
{
|
||||||
|
private static $file = "../content/.session";
|
||||||
|
private static $data = [
|
||||||
|
"member" => "",
|
||||||
|
"token" => "",
|
||||||
|
"form_token" => "",
|
||||||
|
];
|
||||||
|
public static function start()
|
||||||
|
{
|
||||||
|
if (!is_file(self::$file)) {
|
||||||
|
file_put_contents(self::$file, json_encode(self::$data));
|
||||||
|
} else {
|
||||||
|
($new = fopen(self::$file, "w")) or die("Unable to open file!");
|
||||||
|
fwrite($new, json_encode(self::$data));
|
||||||
|
fclose($new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function active()
|
||||||
|
{
|
||||||
|
if (!is_file(self::$file)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$data = json_decode(file_get_contents(self::$file), true);
|
||||||
|
if ($data["member"] != null) {
|
||||||
|
$secret = (new Settings())->getFolks("secret");
|
||||||
|
if ($secret == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
Token::validate($data["token"], $secret) &&
|
||||||
|
Token::validateExpiration($data["token"], $secret)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function verifyToken($token)
|
||||||
|
{
|
||||||
|
$data = json_decode(file_get_contents(self::$file), true);
|
||||||
|
if ($data["member"] != null) {
|
||||||
|
$secret = (new Settings())->getFolks("secret");
|
||||||
|
if (
|
||||||
|
Token::validate($token, $secret) &&
|
||||||
|
Token::validateExpiration($token, $secret)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function set($key, $value)
|
||||||
|
{
|
||||||
|
$data = json_decode(file_get_contents(self::$file), true);
|
||||||
|
$data[$key] = $value;
|
||||||
|
($fresh = fopen(self::$file, "w")) or die("Unable to open file!");
|
||||||
|
fwrite($fresh, json_encode($data));
|
||||||
|
fclose($fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get($key)
|
||||||
|
{
|
||||||
|
$data = json_decode(file_get_contents(self::$file), true);
|
||||||
|
|
||||||
|
return $data[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function kill()
|
||||||
|
{
|
||||||
|
($fresh = fopen(self::$file, "w")) or die("Unable to open file!");
|
||||||
|
fwrite($fresh, json_encode(self::$data));
|
||||||
|
fclose($fresh);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,93 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
use ReallySimpleJWT\Token;
|
|
||||||
|
|
||||||
class Session
|
|
||||||
{
|
|
||||||
private static $file = '../content/.session';
|
|
||||||
private static $data = [
|
|
||||||
'member' => '',
|
|
||||||
'token' => '',
|
|
||||||
'form_token' => '',
|
|
||||||
];
|
|
||||||
|
|
||||||
public static function start()
|
|
||||||
{
|
|
||||||
if (!is_file(self::$file)) {
|
|
||||||
file_put_contents(self::$file, json_encode(self::$data));
|
|
||||||
} else {
|
|
||||||
($new = fopen(self::$file, 'w')) or die('Unable to open file!');
|
|
||||||
fwrite($new, json_encode(self::$data));
|
|
||||||
fclose($new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function active()
|
|
||||||
{
|
|
||||||
if (!is_file(self::$file)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
$data = json_decode(file_get_contents(self::$file), true);
|
|
||||||
if ($data['member'] != null) {
|
|
||||||
$secret = (new Settings())->getFolks('secret');
|
|
||||||
if ($secret == null) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
Token::validate($data['token'], $secret) &&
|
|
||||||
Token::validateExpiration($data['token'], $secret)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function verifyToken($token)
|
|
||||||
{
|
|
||||||
$data = json_decode(file_get_contents(self::$file), true);
|
|
||||||
if ($data['member'] != null) {
|
|
||||||
$secret = (new Settings())->getFolks('secret');
|
|
||||||
if (
|
|
||||||
Token::validate($token, $secret) &&
|
|
||||||
Token::validateExpiration($token, $secret)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function set($key, $value)
|
|
||||||
{
|
|
||||||
$data = json_decode(file_get_contents(self::$file), true);
|
|
||||||
$data[$key] = $value;
|
|
||||||
($fresh = fopen(self::$file, 'w')) or die('Unable to open file!');
|
|
||||||
fwrite($fresh, json_encode($data));
|
|
||||||
fclose($fresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function get($key)
|
|
||||||
{
|
|
||||||
$data = json_decode(file_get_contents(self::$file), true);
|
|
||||||
|
|
||||||
return $data[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function kill()
|
|
||||||
{
|
|
||||||
($fresh = fopen(self::$file, 'w')) or die('Unable to open file!');
|
|
||||||
fwrite($fresh, json_encode(self::$data));
|
|
||||||
fclose($fresh);
|
|
||||||
}
|
|
||||||
}
|
|
169
brain/data/Settings.inc.php
Normal file
169
brain/data/Settings.inc.php
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
<?php
|
||||||
|
use function _\find;
|
||||||
|
use function _\pull;
|
||||||
|
use function _\remove;
|
||||||
|
class Settings
|
||||||
|
{
|
||||||
|
private $folks;
|
||||||
|
private static $tags;
|
||||||
|
private static $settings;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//gets all settings files and converts to php objects
|
||||||
|
$this->folks = json_decode(file_get_contents("../config/folks.json"), true);
|
||||||
|
self::$tags = json_decode(file_get_contents("../config/tags.json"), true);
|
||||||
|
self::$settings = json_decode(
|
||||||
|
file_get_contents("../config/settings.json"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function sync($data)
|
||||||
|
{
|
||||||
|
$settings = self::$settings;
|
||||||
|
$settings["global"]["base_url"] = $data["global"]["base_url"];
|
||||||
|
$settings["global"]["title"] = $data["global"]["title"];
|
||||||
|
$settings["global"]["descriptions"] = $data["global"]["descriptions"];
|
||||||
|
$settings["global"]["base_url"] = $data["global"]["base_url"];
|
||||||
|
$settings["global"]["private"] = $data["global"]["private"];
|
||||||
|
$settings["global"]["renderOnSave"] = $data["global"]["renderOnSave"];
|
||||||
|
$settings["global"]["theme"] = $data["global"]["theme"];
|
||||||
|
$settings["global"]["externalAPI"] = $data["global"]["externalAPI"];
|
||||||
|
$settings["global"]["dynamicRender"] = $data["global"]["dynamicRender"];
|
||||||
|
|
||||||
|
Member::updateData("handle", $data["member"]["handle"]);
|
||||||
|
Member::updateData("email", $data["member"]["email"]);
|
||||||
|
|
||||||
|
$settings["email"]["active"] = $data["email"]["active"];
|
||||||
|
$settings["email"]["smtp"] = $data["email"]["smtp"];
|
||||||
|
$settings["email"]["mailgun"] = $data["email"]["mailgun"];
|
||||||
|
|
||||||
|
DocTools::writeSettings("../config/settings.json", $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function navSync($data)
|
||||||
|
{
|
||||||
|
$settings = self::$settings;
|
||||||
|
|
||||||
|
$remove = $data["remove"];
|
||||||
|
//if remove contains id, find nav item page and set menu to false
|
||||||
|
if ($remove != null || $remove != "") {
|
||||||
|
$page = (new Book("../content/pages"))->findPageById($remove);
|
||||||
|
$page["menu"] = "false";
|
||||||
|
$page["published"]
|
||||||
|
? ($page["published"] = "true")
|
||||||
|
: ($page["published"] = "false");
|
||||||
|
$page["featured"]
|
||||||
|
? ($page["featured"] = "true")
|
||||||
|
: ($page["featured"] = "false");
|
||||||
|
$page["deleted"]
|
||||||
|
? ($page["deleted"] = "true")
|
||||||
|
: ($page["deleted"] = "false");
|
||||||
|
$updated = new \Moment\Moment();
|
||||||
|
$created = new \Moment\Moment($page["rawCreated"]);
|
||||||
|
$page["created"] = $created->format("Y-m-d\TH:i:sP");
|
||||||
|
$page["updated"] = $updated->format("Y-m-d\TH:i:sP");
|
||||||
|
|
||||||
|
$md = DocTools::objectToMD($page);
|
||||||
|
|
||||||
|
if ($page["layout"] == "index") {
|
||||||
|
$writePath = "../content/pages/start/index.md";
|
||||||
|
} else {
|
||||||
|
$writePath =
|
||||||
|
"../content/pages/" . $page["path"] . "/" . $page["slug"] . ".md";
|
||||||
|
}
|
||||||
|
|
||||||
|
DocTools::writePages("write", $page["path"], $writePath, $md);
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings["menu"] = [];
|
||||||
|
$items = $data["menu"];
|
||||||
|
foreach ($items as $item) {
|
||||||
|
array_push($settings["menu"], [
|
||||||
|
"title" => $item["title"],
|
||||||
|
"id" => $item["id"],
|
||||||
|
"uuid" => $item["uuid"],
|
||||||
|
"slug" => $item["slug"],
|
||||||
|
"path" => $item["path"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DocTools::writeSettings("../config/settings.json", $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFolks($key = null)
|
||||||
|
{
|
||||||
|
if (isset($key)) {
|
||||||
|
$member = Session::get("member");
|
||||||
|
$found = find($this->folks, ["handle" => $member["handle"]]);
|
||||||
|
if ($found) {
|
||||||
|
return $found[$key];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->folks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSettings($key = null)
|
||||||
|
{
|
||||||
|
return self::$settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getTags()
|
||||||
|
{
|
||||||
|
return self::$tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function updateGlobalData($key, $data)
|
||||||
|
{
|
||||||
|
$settings = self::$settings;
|
||||||
|
$settings["global"][$key] = $data;
|
||||||
|
DocTools::writeSettings("../config/settings.json", $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCurrentIndex()
|
||||||
|
{
|
||||||
|
$settings = self::$settings;
|
||||||
|
return $settings["library_stats"]["current_index"];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function updateIndex()
|
||||||
|
{
|
||||||
|
$settings = self::$settings;
|
||||||
|
|
||||||
|
$settings["library_stats"]["current_index"] =
|
||||||
|
$settings["library_stats"]["current_index"] + 1;
|
||||||
|
|
||||||
|
DocTools::writeSettings("../config/settings.json", $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function updateMenu($body)
|
||||||
|
{
|
||||||
|
$settings = self::$settings;
|
||||||
|
//$menu = $settings["menu"];
|
||||||
|
$item = [
|
||||||
|
"title" => $body["title"],
|
||||||
|
"id" => $body["id"],
|
||||||
|
"uuid" => $body["uuid"],
|
||||||
|
"slug" => $body["slug"],
|
||||||
|
"path" => $body["path"],
|
||||||
|
];
|
||||||
|
if ($body["menu"] == "true") {
|
||||||
|
if (!find($settings["menu"], ["uuid" => $item["uuid"]])) {
|
||||||
|
array_push($settings["menu"], $item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (find($settings["menu"], ["uuid" => $item["uuid"]])) {
|
||||||
|
pull($settings["menu"], $item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DocTools::writeSettings("../config/settings.json", $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function updateTags()
|
||||||
|
{
|
||||||
|
$tags = Sorting::tags();
|
||||||
|
DocTools::writeSettings("../config/tags.json", $tags);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,175 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
use brain\utility\DocTools;
|
|
||||||
use brain\utility\Sorting;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
use function _\find;
|
|
||||||
use function _\pull;
|
|
||||||
use function _\remove;
|
|
||||||
|
|
||||||
class Settings
|
|
||||||
{
|
|
||||||
private $folks;
|
|
||||||
private static $tags;
|
|
||||||
private static $settings;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
//gets all settings files and converts to php objects
|
|
||||||
$this->folks = json_decode(file_get_contents('../config/folks.json'), true);
|
|
||||||
self::$tags = json_decode(file_get_contents('../config/tags.json'), true);
|
|
||||||
self::$settings = json_decode(
|
|
||||||
file_get_contents('../config/settings.json'),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function sync($data)
|
|
||||||
{
|
|
||||||
$settings = self::$settings;
|
|
||||||
$settings['global']['base_url'] = $data['global']['base_url'];
|
|
||||||
$settings['global']['title'] = $data['global']['title'];
|
|
||||||
$settings['global']['descriptions'] = $data['global']['descriptions'];
|
|
||||||
$settings['global']['base_url'] = $data['global']['base_url'];
|
|
||||||
$settings['global']['private'] = $data['global']['private'];
|
|
||||||
$settings['global']['renderOnSave'] = $data['global']['renderOnSave'];
|
|
||||||
$settings['global']['theme'] = $data['global']['theme'];
|
|
||||||
$settings['global']['externalAPI'] = $data['global']['externalAPI'];
|
|
||||||
$settings['global']['dynamicRender'] = $data['global']['dynamicRender'];
|
|
||||||
|
|
||||||
Member::updateData('handle', $data['member']['handle']);
|
|
||||||
Member::updateData('email', $data['member']['email']);
|
|
||||||
|
|
||||||
$settings['email']['active'] = $data['email']['active'];
|
|
||||||
$settings['email']['smtp'] = $data['email']['smtp'];
|
|
||||||
$settings['email']['mailgun'] = $data['email']['mailgun'];
|
|
||||||
|
|
||||||
DocTools::writeSettings('../config/settings.json', $settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function navSync($data)
|
|
||||||
{
|
|
||||||
$settings = self::$settings;
|
|
||||||
|
|
||||||
$remove = $data['remove'];
|
|
||||||
//if remove contains id, find nav item page and set menu to false
|
|
||||||
if ($remove != null || $remove != '') {
|
|
||||||
$page = (new Book('../content/pages'))->findPageById($remove);
|
|
||||||
$page['menu'] = 'false';
|
|
||||||
$page['published']
|
|
||||||
? ($page['published'] = 'true')
|
|
||||||
: ($page['published'] = 'false');
|
|
||||||
$page['featured']
|
|
||||||
? ($page['featured'] = 'true')
|
|
||||||
: ($page['featured'] = 'false');
|
|
||||||
$page['deleted']
|
|
||||||
? ($page['deleted'] = 'true')
|
|
||||||
: ($page['deleted'] = 'false');
|
|
||||||
$updated = Carbon::now();
|
|
||||||
$created = new Carbon($page['rawCreated']);
|
|
||||||
$page['created'] = $created->format("Y-m-d\TH:i:sP");
|
|
||||||
$page['updated'] = $updated->format("Y-m-d\TH:i:sP");
|
|
||||||
|
|
||||||
$md = DocTools::objectToMD($page);
|
|
||||||
|
|
||||||
if ($page['layout'] == 'index') {
|
|
||||||
$writePath = '../content/pages/start/index.md';
|
|
||||||
} else {
|
|
||||||
$writePath = '../content/pages/' . $page['path'] . '/' . $page['slug'] . '.md';
|
|
||||||
}
|
|
||||||
|
|
||||||
DocTools::writePages('write', $page['path'], $writePath, $md);
|
|
||||||
}
|
|
||||||
|
|
||||||
$settings['menu'] = [];
|
|
||||||
$items = $data['menu'];
|
|
||||||
foreach ($items as $item) {
|
|
||||||
array_push($settings['menu'], [
|
|
||||||
'title' => $item['title'],
|
|
||||||
'id' => $item['id'],
|
|
||||||
'uuid' => $item['uuid'],
|
|
||||||
'slug' => $item['slug'],
|
|
||||||
'path' => $item['path'],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
DocTools::writeSettings('../config/settings.json', $settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFolks($key = null)
|
|
||||||
{
|
|
||||||
if (isset($key)) {
|
|
||||||
$member = Session::get('member');
|
|
||||||
$found = find($this->folks, ['handle' => $member['handle']]);
|
|
||||||
if ($found) {
|
|
||||||
return $found[$key];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return $this->folks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSettings($key = null)
|
|
||||||
{
|
|
||||||
return self::$settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getTags()
|
|
||||||
{
|
|
||||||
return self::$tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function updateGlobalData($key, $data)
|
|
||||||
{
|
|
||||||
$settings = self::$settings;
|
|
||||||
$settings['global'][$key] = $data;
|
|
||||||
DocTools::writeSettings('../config/settings.json', $settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getCurrentIndex()
|
|
||||||
{
|
|
||||||
$settings = self::$settings;
|
|
||||||
return $settings['library_stats']['current_index'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function updateIndex()
|
|
||||||
{
|
|
||||||
$settings = self::$settings;
|
|
||||||
|
|
||||||
$settings['library_stats']['current_index'] = $settings['library_stats']['current_index'] + 1;
|
|
||||||
|
|
||||||
DocTools::writeSettings('../config/settings.json', $settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function updateMenu($body)
|
|
||||||
{
|
|
||||||
$settings = self::$settings;
|
|
||||||
//$menu = $settings["menu"];
|
|
||||||
$item = [
|
|
||||||
'title' => $body['title'],
|
|
||||||
'id' => $body['id'],
|
|
||||||
'uuid' => $body['uuid'],
|
|
||||||
'slug' => $body['slug'],
|
|
||||||
'path' => $body['path'],
|
|
||||||
];
|
|
||||||
if ($body['menu'] == 'true') {
|
|
||||||
if (!find($settings['menu'], ['uuid' => $item['uuid']])) {
|
|
||||||
array_push($settings['menu'], $item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (find($settings['menu'], ['uuid' => $item['uuid']])) {
|
|
||||||
pull($settings['menu'], $item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DocTools::writeSettings('../config/settings.json', $settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function updateTags()
|
|
||||||
{
|
|
||||||
$tags = Sorting::tags();
|
|
||||||
DocTools::writeSettings('../config/tags.json', $tags);
|
|
||||||
}
|
|
||||||
}
|
|
41
brain/data/Themes.inc.php
Normal file
41
brain/data/Themes.inc.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Themes
|
||||||
|
{
|
||||||
|
private $themes = [];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$_themes = glob("../content/themes/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($_themes as $theme) {
|
||||||
|
array_push(
|
||||||
|
$this->themes,
|
||||||
|
json_decode(file_get_contents($theme . "/theme.json"), true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getThemes()
|
||||||
|
{
|
||||||
|
return $this->themes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomViews()
|
||||||
|
{
|
||||||
|
$settings = (new Settings())->getSettings();
|
||||||
|
$currentTheme = $settings["global"]["theme"];
|
||||||
|
$folder = "../content/themes/" . $currentTheme;
|
||||||
|
$files = array_filter(glob("$folder/*twig"), "is_file");
|
||||||
|
$views = [];
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$path = explode("/", $file);
|
||||||
|
$fileName = $path[4];
|
||||||
|
if (str_contains($fileName, "page")) {
|
||||||
|
$page = explode(".", $fileName);
|
||||||
|
$views[] = $page[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $views;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\data;
|
|
||||||
|
|
||||||
class Themes
|
|
||||||
{
|
|
||||||
private $themes = [];
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$_themes = glob('../content/themes/*', GLOB_ONLYDIR);
|
|
||||||
foreach ($_themes as $theme) {
|
|
||||||
array_push(
|
|
||||||
$this->themes,
|
|
||||||
json_decode(file_get_contents($theme . '/theme.json'), true)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getThemes()
|
|
||||||
{
|
|
||||||
return $this->themes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCustomIndex()
|
|
||||||
{
|
|
||||||
$settings = (new Settings())->getSettings();
|
|
||||||
$currentTheme = $settings['global']['theme'];
|
|
||||||
$folder = '../content/themes/' . $currentTheme;
|
|
||||||
$files = array_filter(glob("$folder/*twig"), 'is_file');
|
|
||||||
$views = [];
|
|
||||||
|
|
||||||
foreach ($files as $file) {
|
|
||||||
$path = explode('/', $file);
|
|
||||||
$fileName = $path[4];
|
|
||||||
if (str_contains($fileName, 'index')) {
|
|
||||||
$page = explode('.', $fileName);
|
|
||||||
$views[] = $page[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $views;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCustomViews()
|
|
||||||
{
|
|
||||||
$settings = (new Settings())->getSettings();
|
|
||||||
$currentTheme = $settings['global']['theme'];
|
|
||||||
$folder = '../content/themes/' . $currentTheme;
|
|
||||||
$files = array_filter(glob("$folder/*twig"), 'is_file');
|
|
||||||
$views = [];
|
|
||||||
|
|
||||||
foreach ($files as $file) {
|
|
||||||
$path = explode('/', $file);
|
|
||||||
$fileName = $path[4];
|
|
||||||
if (str_contains($fileName, 'page')) {
|
|
||||||
$page = explode('.', $fileName);
|
|
||||||
$views[] = $page[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $views;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\init;
|
|
||||||
|
|
||||||
use brain\utility\HandleCors;
|
|
||||||
use Slim\Factory\AppFactory;
|
|
||||||
use Slim\Views\Twig;
|
|
||||||
use Slim\Views\TwigMiddleware;
|
|
||||||
|
|
||||||
class App
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
// when a new class is made, run composer dump-autoload
|
|
||||||
// set up cors
|
|
||||||
new HandleCors();
|
|
||||||
$app = AppFactory::create();
|
|
||||||
$twig = Twig::create('../brain/views/');
|
|
||||||
$app->add(TwigMiddleware::create($app, $twig));
|
|
||||||
// set up routing
|
|
||||||
$app->get(
|
|
||||||
'/[{first}[/{second}[/{third}[/{fourth}[/{fifth}]]]]]',
|
|
||||||
"brain\controller\RouteControl:get"
|
|
||||||
);
|
|
||||||
$app->post(
|
|
||||||
'/[{first}[/{second}[/{third}[/{fourth}]]]]',
|
|
||||||
"brain\controller\RouteControl:post"
|
|
||||||
);
|
|
||||||
// start the app
|
|
||||||
|
|
||||||
$app->run();
|
|
||||||
}
|
|
||||||
}
|
|
140
brain/utility/DocTools.inc.php
Normal file
140
brain/utility/DocTools.inc.php
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class DocTools
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function writePages($task, $path, $fileLocation, $fileContents)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($task == "create") {
|
||||||
|
if (!is_dir("../content/pages/" . $path)) {
|
||||||
|
//Directory does not exist, so lets create it.
|
||||||
|
mkdir("../content/pages/" . $path, 0755, true);
|
||||||
|
}
|
||||||
|
file_put_contents($fileLocation, $fileContents);
|
||||||
|
} else {
|
||||||
|
($new = fopen($fileLocation, "w")) or die("Unable to open file!");
|
||||||
|
fwrite($new, $fileContents);
|
||||||
|
fclose($new);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Error $error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function writeSettings($fileLocation, $fileContents)
|
||||||
|
{
|
||||||
|
if (!is_file($fileLocation)) {
|
||||||
|
file_put_contents($fileLocation, json_encode($fileContents));
|
||||||
|
} else {
|
||||||
|
($new = fopen($fileLocation, "w")) or die("Unable to open file!");
|
||||||
|
fwrite($new, json_encode($fileContents));
|
||||||
|
fclose($new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function writeHTML($location, $html, $path = null)
|
||||||
|
{
|
||||||
|
if ($path != null) {
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
//Directory does not exist, so lets create it.
|
||||||
|
mkdir($path, 0755, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!is_file($location)) {
|
||||||
|
file_put_contents($location, $html);
|
||||||
|
} else {
|
||||||
|
($new = fopen($location, "w")) or die("Unable to open file!");
|
||||||
|
fwrite($new, $html);
|
||||||
|
fclose($new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deleteFolder($path)
|
||||||
|
{
|
||||||
|
if (!empty($path) && is_dir($path)) {
|
||||||
|
$dir = new RecursiveDirectoryIterator(
|
||||||
|
$path,
|
||||||
|
RecursiveDirectoryIterator::SKIP_DOTS
|
||||||
|
); //upper dirs are not included,otherwise DISASTER HAPPENS :)
|
||||||
|
$files = new RecursiveIteratorIterator(
|
||||||
|
$dir,
|
||||||
|
RecursiveIteratorIterator::CHILD_FIRST
|
||||||
|
);
|
||||||
|
foreach ($files as $f) {
|
||||||
|
if (is_file($f)) {
|
||||||
|
unlink($f);
|
||||||
|
} else {
|
||||||
|
$empty_dirs[] = $f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($empty_dirs)) {
|
||||||
|
foreach ($empty_dirs as $eachDir) {
|
||||||
|
rmdir($eachDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmdir($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function objectToMD($object)
|
||||||
|
{
|
||||||
|
$markdown =
|
||||||
|
"---\n" .
|
||||||
|
"id: " .
|
||||||
|
$object["id"] .
|
||||||
|
"\n" .
|
||||||
|
"uuid: " .
|
||||||
|
$object["uuid"] .
|
||||||
|
"\n" .
|
||||||
|
"title: " .
|
||||||
|
"'" .
|
||||||
|
$object["title"] .
|
||||||
|
"'" .
|
||||||
|
"\n" .
|
||||||
|
"feature: " .
|
||||||
|
$object["feature"] .
|
||||||
|
"\n" .
|
||||||
|
"path: " .
|
||||||
|
$object["path"] .
|
||||||
|
"\n" .
|
||||||
|
"layout: " .
|
||||||
|
$object["layout"] .
|
||||||
|
"\n" .
|
||||||
|
"tags: " .
|
||||||
|
$object["tags"] .
|
||||||
|
"\n" .
|
||||||
|
"author: " .
|
||||||
|
$object["author"] .
|
||||||
|
"\n" .
|
||||||
|
"created: " .
|
||||||
|
$object["created"] .
|
||||||
|
"\n" .
|
||||||
|
"updated: " .
|
||||||
|
$object["updated"] .
|
||||||
|
"\n" .
|
||||||
|
"deleted: " .
|
||||||
|
$object["deleted"] .
|
||||||
|
"\n" .
|
||||||
|
"slug: " .
|
||||||
|
$object["slug"] .
|
||||||
|
"\n" .
|
||||||
|
"menu: " .
|
||||||
|
$object["menu"] .
|
||||||
|
"\n" .
|
||||||
|
"published: " .
|
||||||
|
$object["published"] .
|
||||||
|
"\n" .
|
||||||
|
"featured: " .
|
||||||
|
$object["featured"] .
|
||||||
|
"\n---\n" .
|
||||||
|
$object["content"];
|
||||||
|
|
||||||
|
return $markdown;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,144 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\utility;
|
|
||||||
|
|
||||||
class DocTools
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function writePages($task, $path, $fileLocation, $fileContents)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if ($task == 'create') {
|
|
||||||
if (!is_dir('../content/pages/' . $path)) {
|
|
||||||
//Directory does not exist, so lets create it.
|
|
||||||
mkdir('../content/pages/' . $path, 0755, true);
|
|
||||||
}
|
|
||||||
file_put_contents($fileLocation, $fileContents);
|
|
||||||
} else {
|
|
||||||
($new = fopen($fileLocation, 'w')) or die('Unable to open file!');
|
|
||||||
fwrite($new, $fileContents);
|
|
||||||
fclose($new);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (Error $error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function writeSettings($fileLocation, $fileContents)
|
|
||||||
{
|
|
||||||
if (!is_file($fileLocation)) {
|
|
||||||
file_put_contents($fileLocation, json_encode($fileContents));
|
|
||||||
} else {
|
|
||||||
($new = fopen($fileLocation, 'w')) or die('Unable to open file!');
|
|
||||||
fwrite($new, json_encode($fileContents));
|
|
||||||
fclose($new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function writeHTML($location, $html, $path = null)
|
|
||||||
{
|
|
||||||
if ($path != null) {
|
|
||||||
if (!is_dir($path)) {
|
|
||||||
//Directory does not exist, so lets create it.
|
|
||||||
mkdir($path, 0755, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!is_file($location)) {
|
|
||||||
file_put_contents($location, $html);
|
|
||||||
} else {
|
|
||||||
($new = fopen($location, 'w')) or die('Unable to open file!');
|
|
||||||
fwrite($new, $html);
|
|
||||||
fclose($new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function deleteFolder($path)
|
|
||||||
{
|
|
||||||
if (!empty($path) && is_dir($path)) {
|
|
||||||
$dir = new \RecursiveDirectoryIterator(
|
|
||||||
$path,
|
|
||||||
\RecursiveDirectoryIterator::SKIP_DOTS
|
|
||||||
); //upper dirs are not included,otherwise DISASTER HAPPENS :)
|
|
||||||
$files = new \RecursiveIteratorIterator(
|
|
||||||
$dir,
|
|
||||||
\RecursiveIteratorIterator::CHILD_FIRST
|
|
||||||
);
|
|
||||||
foreach ($files as $f) {
|
|
||||||
if (is_file($f)) {
|
|
||||||
unlink($f);
|
|
||||||
} else {
|
|
||||||
$empty_dirs[] = $f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($empty_dirs)) {
|
|
||||||
foreach ($empty_dirs as $eachDir) {
|
|
||||||
rmdir($eachDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rmdir($path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function objectToMD($object)
|
|
||||||
{
|
|
||||||
$markdown = "---\n" .
|
|
||||||
'id: ' .
|
|
||||||
$object['id'] .
|
|
||||||
"\n" .
|
|
||||||
'uuid: ' .
|
|
||||||
$object['uuid'] .
|
|
||||||
"\n" .
|
|
||||||
'title: ' .
|
|
||||||
"'" .
|
|
||||||
$object['title'] .
|
|
||||||
"'" .
|
|
||||||
"\n" .
|
|
||||||
'feature: ' .
|
|
||||||
$object['imageList'] .
|
|
||||||
"\n" .
|
|
||||||
'files: ' .
|
|
||||||
$object['fileList'] .
|
|
||||||
"\n" .
|
|
||||||
'path: ' .
|
|
||||||
$object['path'] .
|
|
||||||
"\n" .
|
|
||||||
'layout: ' .
|
|
||||||
$object['layout'] .
|
|
||||||
"\n" .
|
|
||||||
'tags: ' .
|
|
||||||
$object['tags'] .
|
|
||||||
"\n" .
|
|
||||||
'author: ' .
|
|
||||||
$object['author'] .
|
|
||||||
"\n" .
|
|
||||||
'created: ' .
|
|
||||||
$object['created'] .
|
|
||||||
"\n" .
|
|
||||||
'updated: ' .
|
|
||||||
$object['updated'] .
|
|
||||||
"\n" .
|
|
||||||
'deleted: ' .
|
|
||||||
$object['deleted'] .
|
|
||||||
"\n" .
|
|
||||||
'slug: ' .
|
|
||||||
$object['slug'] .
|
|
||||||
"\n" .
|
|
||||||
'menu: ' .
|
|
||||||
$object['menu'] .
|
|
||||||
"\n" .
|
|
||||||
'published: ' .
|
|
||||||
$object['published'] .
|
|
||||||
"\n" .
|
|
||||||
'featured: ' .
|
|
||||||
$object['featured'] .
|
|
||||||
"\n---\n" .
|
|
||||||
$object['content'];
|
|
||||||
|
|
||||||
return $markdown;
|
|
||||||
}
|
|
||||||
}
|
|
32
brain/utility/FileUploader.inc.php
Normal file
32
brain/utility/FileUploader.inc.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
use Psr\Http\Message\UploadedFileInterface;
|
||||||
|
//include "brain/data/Auth.inc.php";
|
||||||
|
define("MAXIMUM_FILESIZE", "10485760"); //10 MB
|
||||||
|
class FileUploader
|
||||||
|
{
|
||||||
|
public static function uploadFile(string $directory, $file)
|
||||||
|
{
|
||||||
|
$response = [];
|
||||||
|
try {
|
||||||
|
if (!is_dir($directory)) {
|
||||||
|
//Directory does not exist, so lets create it.
|
||||||
|
mkdir($directory, 0755, true);
|
||||||
|
}
|
||||||
|
//$upload = move_uploaded_file($file->getClientFileName(), $directory);
|
||||||
|
//$extension = pathinfo($file->getClientFilename(), PATHINFO_EXTENSION);
|
||||||
|
|
||||||
|
// see http://php.net/manual/en/function.random-bytes.php
|
||||||
|
//$basename = bin2hex(random_bytes(8));
|
||||||
|
//$filename = sprintf("%s.%0.8s", $basename, $extension);
|
||||||
|
|
||||||
|
//echo "**FILE** " . $file->getClientFileName();
|
||||||
|
|
||||||
|
$file->moveTo($directory . "/" . $file->getClientFileName());
|
||||||
|
} catch (RuntimeException $e) {
|
||||||
|
echo "ERROR " . $e->getMessage();
|
||||||
|
|
||||||
|
//echo "failed to upload image: " . $e->getMessage();
|
||||||
|
//throw new Error("Failed to upload image file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\utility;
|
|
||||||
|
|
||||||
class FileUploader
|
|
||||||
{
|
|
||||||
public static function uploadFile(string $directory, $file)
|
|
||||||
{
|
|
||||||
$response = [];
|
|
||||||
try {
|
|
||||||
if (!is_dir($directory)) {
|
|
||||||
// Directory does not exist, so lets create it.
|
|
||||||
mkdir($directory, 0755, true);
|
|
||||||
}
|
|
||||||
// $upload = move_uploaded_file($file->getClientFileName(), $directory);
|
|
||||||
// $extension = pathinfo($file->getClientFilename(), PATHINFO_EXTENSION);
|
|
||||||
|
|
||||||
// see http://php.net/manual/en/function.random-bytes.php
|
|
||||||
// $basename = bin2hex(random_bytes(8));
|
|
||||||
// $filename = sprintf("%s.%0.8s", $basename, $extension);
|
|
||||||
|
|
||||||
// echo "**FILE** " . $file->getClientFileName();
|
|
||||||
|
|
||||||
$file->moveTo($directory . '/' . urlencode($file->getClientFileName()));
|
|
||||||
} catch (RuntimeException $e) {
|
|
||||||
echo 'ERROR ' . $e->getMessage();
|
|
||||||
|
|
||||||
// echo "failed to upload image: " . $e->getMessage();
|
|
||||||
// throw new Error("Failed to upload image file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +1,41 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace brain\utility;
|
class handleCors
|
||||||
|
|
||||||
use brain\data\Settings;
|
|
||||||
|
|
||||||
class HandleCors
|
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
//look to see if settings file exists. kinda important
|
//look to see if settings file exists. kinda important
|
||||||
if (file_exists('../config/settings.json')) {
|
if (file_exists("../config/settings.json")) {
|
||||||
//check settings to see if external api access is allowed
|
//check settings to see if external api access is allowed
|
||||||
$config = new Settings();
|
$config = new Settings();
|
||||||
$settings = $config->getSettings();
|
$settings = $config->getSettings();
|
||||||
if ($settings['global']['externalAPI']) {
|
if ($settings["global"]["externalAPI"]) {
|
||||||
//echo "API STATUS: " . $settings["global"]["externalAPI"];
|
//echo "API STATUS: " . $settings["global"]["externalAPI"];
|
||||||
if ($settings['global']['externalAPI'] == 'true') {
|
if ($settings["global"]["externalAPI"] == "true") {
|
||||||
//echo "API ACCESS ACTIVE";
|
//echo "API ACCESS ACTIVE";
|
||||||
// checks to see if origin is set
|
// checks to see if origin is set
|
||||||
if (isset($_SERVER['HTTP_ORIGIN'])) {
|
if (isset($_SERVER["HTTP_ORIGIN"])) {
|
||||||
// You can decide if the origin in $_SERVER['HTTP_ORIGIN']
|
// You can decide if the origin in $_SERVER['HTTP_ORIGIN'] is something you want to allow, or as we do here, just allow all
|
||||||
//is something you want to allow, or as we do here, just allow all
|
header("Access-Control-Allow-Origin: {$_SERVER["HTTP_ORIGIN"]}");
|
||||||
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
|
|
||||||
} else {
|
} else {
|
||||||
//No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
|
//No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
|
||||||
//never allow just any domain, so turn CORS off if no No HTTP_ORIGIN is set
|
//never allow just any domain, so turn CORS off if no No HTTP_ORIGIN is set
|
||||||
//header("Access-Control-Allow-Origin: *");
|
//header("Access-Control-Allow-Origin: *");
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Access-Control-Allow-Credentials: true');
|
header("Access-Control-Allow-Credentials: true");
|
||||||
header('Access-Control-Max-Age: 600'); // cache for 10 minutes
|
header("Access-Control-Max-Age: 600"); // cache for 10 minutes
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
|
if ($_SERVER["REQUEST_METHOD"] == "OPTIONS") {
|
||||||
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
|
if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"])) {
|
||||||
header(
|
header(
|
||||||
'Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT'
|
"Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT"
|
||||||
);
|
);
|
||||||
} //Make sure you remove those you do not want to support
|
} //Make sure you remove those you do not want to support
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
|
if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"])) {
|
||||||
header(
|
header(
|
||||||
"Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"
|
"Access-Control-Allow-Headers: {$_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
94
brain/utility/Mailer.inc.php
Normal file
94
brain/utility/Mailer.inc.php
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
use Slim\Views\Twig;
|
||||||
|
|
||||||
|
use PHPMailer\PHPMailer\PHPMailer;
|
||||||
|
use PHPMailer\PHPMailer\Exception;
|
||||||
|
|
||||||
|
class Mailer
|
||||||
|
{
|
||||||
|
public static function sendMail($body)
|
||||||
|
{
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$mailConfig = $settings["email"];
|
||||||
|
$mail = new PHPMailer();
|
||||||
|
|
||||||
|
switch ($body["mail_task"]) {
|
||||||
|
case "TESTING":
|
||||||
|
$html =
|
||||||
|
"<h1>Hi! It's Fipamo!</h1><br>" .
|
||||||
|
"<strong>It's just a test</strong><br>" .
|
||||||
|
$body["content"];
|
||||||
|
$member = Session::get("member");
|
||||||
|
$mail->addAddress($member["email"], ""); //pull email address from current user
|
||||||
|
$mail->Subject = "A test email";
|
||||||
|
break;
|
||||||
|
case "SEND_SECRET":
|
||||||
|
$html =
|
||||||
|
"<h1>Hi! It's Fipamo!</h1><br>" .
|
||||||
|
"<strong>This is your secret key.</strong><br><br>" .
|
||||||
|
"<h3>" .
|
||||||
|
$body["secret"] .
|
||||||
|
"</h3>" .
|
||||||
|
"<br> Use this key to reset your password.";
|
||||||
|
$mail->addAddress($body["email"], ""); //pull email address from current user
|
||||||
|
$mail->Subject = "Shhhh! It's a secret!";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return $result = [
|
||||||
|
"type" => "noMailService",
|
||||||
|
"message" => "Mail task is undefined. What are you doing??",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set values based on current active protocol
|
||||||
|
switch ($mailConfig["active"]) {
|
||||||
|
case "option-smtp":
|
||||||
|
$mail->setFrom($mailConfig["smtp"]["email"], "System Email");
|
||||||
|
$mail->Host = "playvicio.us";
|
||||||
|
$mail->Username = $mailConfig["smtp"]["email"];
|
||||||
|
$mail->Password = $mailConfig["smtp"]["password"];
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "option-mg":
|
||||||
|
$mail->setFrom($mailConfig["mailgun"]["domain"], "No Reply");
|
||||||
|
$mail->Host = "smtp.mailgun.org";
|
||||||
|
$mail->Username = $mailConfig["mailgun"]["domain"];
|
||||||
|
$mail->Password = $mailConfig["mailgun"]["key"];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//no mail service
|
||||||
|
return $result = [
|
||||||
|
"type" => "noMailService",
|
||||||
|
"message" => "Mail is not configured. Handle that.",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mail->Body = $html;
|
||||||
|
$mail->IsHTML(true);
|
||||||
|
$mail->isSMTP();
|
||||||
|
$mail->SMTPAuth = true;
|
||||||
|
$mail->SMTPSecure = "ssl";
|
||||||
|
$mail->Port = 465;
|
||||||
|
|
||||||
|
// Uncomment for debug info
|
||||||
|
//$mail->SMTPDebug = 4;
|
||||||
|
|
||||||
|
/* Finally send the mail. */
|
||||||
|
try {
|
||||||
|
$mail->send();
|
||||||
|
$result = ["type" => "mailSent", "message" => "Message Away!"];
|
||||||
|
} catch (Exception $e) {
|
||||||
|
//echo $e->errorMessage();
|
||||||
|
$result = [
|
||||||
|
"type" => "mailNotSent",
|
||||||
|
"message" => "Message Not Away!",
|
||||||
|
"error" => $e->errorMessage(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,95 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\utility;
|
|
||||||
|
|
||||||
use PHPMailer\PHPMailer\PHPMailer;
|
|
||||||
use PHPMailer\PHPMailer\Exception;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use brain\data\Session;
|
|
||||||
|
|
||||||
class Mailer
|
|
||||||
{
|
|
||||||
public static function sendMail($body)
|
|
||||||
{
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$mailConfig = $settings['email'];
|
|
||||||
$mail = new PHPMailer();
|
|
||||||
|
|
||||||
switch ($body['mail_task']) {
|
|
||||||
case 'TESTING':
|
|
||||||
$html = "<h1>Hi! It's Fipamo!</h1><br>" .
|
|
||||||
"<strong>It's just a test</strong><br>" .
|
|
||||||
$body['content'];
|
|
||||||
$member = Session::get('member');
|
|
||||||
$mail->addAddress($member['email'], ''); //pull email address from current user
|
|
||||||
$mail->Subject = 'A test email';
|
|
||||||
break;
|
|
||||||
case 'SEND_SECRET':
|
|
||||||
$html = "<h1>Hi! It's Fipamo!</h1><br>" .
|
|
||||||
'<strong>This is your secret key.</strong><br><br>' .
|
|
||||||
'<h3>' .
|
|
||||||
$body['secret'] .
|
|
||||||
'</h3>' .
|
|
||||||
'<br> Use this key to reset your password.';
|
|
||||||
$mail->addAddress($body['email'], ''); //pull email address from current user
|
|
||||||
$mail->Subject = "Shhhh! It's a secret!";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return $result = [
|
|
||||||
'type' => 'noMailService',
|
|
||||||
'message' => 'Mail task is undefined. What are you doing??',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//set values based on current active protocol
|
|
||||||
switch ($mailConfig['active']) {
|
|
||||||
case 'option-smtp':
|
|
||||||
$mail->setFrom($mailConfig['smtp']['email'], 'System Email');
|
|
||||||
$mail->Host = 'playvicio.us';
|
|
||||||
$mail->Username = $mailConfig['smtp']['email'];
|
|
||||||
$mail->Password = $mailConfig['smtp']['password'];
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'option-mg':
|
|
||||||
$mail->setFrom($mailConfig['mailgun']['domain'], 'No Reply');
|
|
||||||
$mail->Host = 'smtp.mailgun.org';
|
|
||||||
$mail->Username = $mailConfig['mailgun']['domain'];
|
|
||||||
$mail->Password = $mailConfig['mailgun']['key'];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//no mail service
|
|
||||||
return $result = [
|
|
||||||
'type' => 'noMailService',
|
|
||||||
'message' => 'Mail is not configured. Handle that.',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mail->Body = $html;
|
|
||||||
$mail->IsHTML(true);
|
|
||||||
$mail->isSMTP();
|
|
||||||
$mail->SMTPAuth = true;
|
|
||||||
$mail->SMTPSecure = 'ssl';
|
|
||||||
$mail->Port = 465;
|
|
||||||
|
|
||||||
// Uncomment for debug info
|
|
||||||
//$mail->SMTPDebug = 4;
|
|
||||||
|
|
||||||
/* Finally send the mail. */
|
|
||||||
try {
|
|
||||||
$mail->send();
|
|
||||||
$result = ['type' => 'mailSent', 'message' => 'Message Away!'];
|
|
||||||
} catch (Exception $e) {
|
|
||||||
//echo $e->errorMessage();
|
|
||||||
$result = [
|
|
||||||
'type' => 'mailNotSent',
|
|
||||||
'message' => 'Message Not Away!',
|
|
||||||
'error' => $e->errorMessage(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
99
brain/utility/Maintenance.inc.php
Normal file
99
brain/utility/Maintenance.inc.php
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
class Maintenance
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function makeBackup()
|
||||||
|
{
|
||||||
|
//make sure back directory is there
|
||||||
|
if (!is_dir("../config/backups")) {
|
||||||
|
mkdir("../config/backups", 0755, true);
|
||||||
|
}
|
||||||
|
//creat backup zip
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
$zip->open(
|
||||||
|
"../config/backups/latest_back.zip",
|
||||||
|
ZipArchive::CREATE | ZipArchive::OVERWRITE
|
||||||
|
);
|
||||||
|
//gather data and path info for md pages
|
||||||
|
$pagePath = "../content/pages";
|
||||||
|
$yearPaths = glob($pagePath . "/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($yearPaths as $years) {
|
||||||
|
$year = explode("/", $years);
|
||||||
|
//grap the index and save it
|
||||||
|
if (trim($year[3]) == "start") {
|
||||||
|
$options = [
|
||||||
|
"add_path" => "content/pages/" . $year[3] . "/",
|
||||||
|
"remove_all_path" => true,
|
||||||
|
];
|
||||||
|
$zip->addGlob($years . "/*.md", GLOB_BRACE, $options);
|
||||||
|
}
|
||||||
|
$monthsPath = glob($pagePath . "/" . $year[3] . "/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($monthsPath as $months) {
|
||||||
|
$month = explode("/", $months);
|
||||||
|
//once info is collected, add md pages to zip
|
||||||
|
$options = [
|
||||||
|
"add_path" => "content/pages/" . $year[3] . "/" . $month[4] . "/",
|
||||||
|
"remove_all_path" => true,
|
||||||
|
];
|
||||||
|
$zip->addGlob($months . "/*.md", GLOB_BRACE, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//gather data and path info for blog images
|
||||||
|
$blogImagesPath = "../public/assets/images/blog";
|
||||||
|
$yearPaths = glob($blogImagesPath . "/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($yearPaths as $years) {
|
||||||
|
$year = explode("/", $years);
|
||||||
|
$monthsPath = glob($blogImagesPath . "/" . $year[5] . "/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($monthsPath as $months) {
|
||||||
|
$month = explode("/", $months);
|
||||||
|
//once info is collected, add images pages to zip
|
||||||
|
$options = [
|
||||||
|
"add_path" =>
|
||||||
|
"public/assets/images/blog/" . $year[5] . "/" . $month[6] . "/",
|
||||||
|
"remove_all_path" => true,
|
||||||
|
];
|
||||||
|
$zip->addGlob($months . "/*.*", GLOB_BRACE, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//gather data and path info for user images
|
||||||
|
$userImagesPath = "../public/assets/images/user";
|
||||||
|
$yearPaths = glob($userImagesPath . "/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($yearPaths as $years) {
|
||||||
|
$year = explode("/", $years);
|
||||||
|
$monthsPath = glob($userImagesPath . "/" . $year[5] . "/*", GLOB_ONLYDIR);
|
||||||
|
foreach ($monthsPath as $months) {
|
||||||
|
$month = explode("/", $months);
|
||||||
|
//once info is collected, add images pages to zip
|
||||||
|
$options = [
|
||||||
|
"add_path" =>
|
||||||
|
"public/assets/images/user/" . $year[5] . "/" . $month[6] . "/",
|
||||||
|
"remove_all_path" => true,
|
||||||
|
];
|
||||||
|
$zip->addGlob($months . "/*.*", GLOB_BRACE, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add directory for settings and save them
|
||||||
|
$zip->addEmptyDir("settings");
|
||||||
|
$zip->addFile("../config/settings.json", "settings/settings.json");
|
||||||
|
$zip->addFile("../config/folks.json", "settings/folks.json");
|
||||||
|
$zip->addFile("../config/tags.json", "settings/tags.json");
|
||||||
|
//save zip file
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
//update settings file with latest back up date
|
||||||
|
$updated = new \Moment\Moment();
|
||||||
|
Settings::updateGlobalData(
|
||||||
|
"last_backup",
|
||||||
|
$updated->format("Y-m-d\TH:i:sP")
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = ["message" => "Backup created. THIS IS A SAFE SPACE!"];
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,103 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\utility;
|
|
||||||
|
|
||||||
use brain\data\Settings;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
class Maintenance
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function makeBackup()
|
|
||||||
{
|
|
||||||
//make sure back directory is there
|
|
||||||
if (!is_dir('../config/backups')) {
|
|
||||||
mkdir('../config/backups', 0755, true);
|
|
||||||
}
|
|
||||||
//creat backup zip
|
|
||||||
$zip = new \ZipArchive();
|
|
||||||
$zip->open(
|
|
||||||
'../config/backups/latest_back.zip',
|
|
||||||
\ZipArchive::CREATE | \ZipArchive::OVERWRITE
|
|
||||||
);
|
|
||||||
//gather data and path info for md pages
|
|
||||||
$pagePath = '../content/pages';
|
|
||||||
$yearPaths = glob($pagePath . '/*', GLOB_ONLYDIR);
|
|
||||||
foreach ($yearPaths as $years) {
|
|
||||||
$year = explode('/', $years);
|
|
||||||
//grap the index and save it
|
|
||||||
if (trim($year[3]) == 'start') {
|
|
||||||
$options = [
|
|
||||||
'add_path' => 'content/pages/' . $year[3] . '/',
|
|
||||||
'remove_all_path' => true,
|
|
||||||
];
|
|
||||||
$zip->addGlob($years . '/*.md', GLOB_BRACE, $options);
|
|
||||||
}
|
|
||||||
$monthsPath = glob($pagePath . '/' . $year[3] . '/*', GLOB_ONLYDIR);
|
|
||||||
foreach ($monthsPath as $months) {
|
|
||||||
$month = explode('/', $months);
|
|
||||||
//once info is collected, add md pages to zip
|
|
||||||
$options = [
|
|
||||||
'add_path' => 'content/pages/' . $year[3] . '/' . $month[4] . '/',
|
|
||||||
'remove_all_path' => true,
|
|
||||||
];
|
|
||||||
$zip->addGlob($months . '/*.md', GLOB_BRACE, $options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//gather data and path info for blog images
|
|
||||||
$blogImagesPath = '../public/assets/images/blog';
|
|
||||||
$yearPaths = glob($blogImagesPath . '/*', GLOB_ONLYDIR);
|
|
||||||
foreach ($yearPaths as $years) {
|
|
||||||
$year = explode('/', $years);
|
|
||||||
$monthsPath = glob($blogImagesPath . '/' . $year[5] . '/*', GLOB_ONLYDIR);
|
|
||||||
foreach ($monthsPath as $months) {
|
|
||||||
$month = explode('/', $months);
|
|
||||||
//once info is collected, add images pages to zip
|
|
||||||
$options = [
|
|
||||||
'add_path' => 'public/assets/images/blog/' . $year[5] . '/' . $month[6] . '/',
|
|
||||||
'remove_all_path' => true,
|
|
||||||
];
|
|
||||||
$zip->addGlob($months . '/*.*', GLOB_BRACE, $options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//gather data and path info for user images
|
|
||||||
$userImagesPath = '../public/assets/images/user';
|
|
||||||
$yearPaths = glob($userImagesPath . '/*', GLOB_ONLYDIR);
|
|
||||||
foreach ($yearPaths as $years) {
|
|
||||||
$year = explode('/', $years);
|
|
||||||
$monthsPath = glob($userImagesPath . '/' . $year[5] . '/*', GLOB_ONLYDIR);
|
|
||||||
foreach ($monthsPath as $months) {
|
|
||||||
$month = explode('/', $months);
|
|
||||||
//once info is collected, add images pages to zip
|
|
||||||
$options = [
|
|
||||||
'add_path' => 'public/assets/images/user/' . $year[5] . '/' . $month[6] . '/',
|
|
||||||
'remove_all_path' => true,
|
|
||||||
];
|
|
||||||
$zip->addGlob($months . '/*.*', GLOB_BRACE, $options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//add directory for settings and save them
|
|
||||||
$zip->addEmptyDir('settings');
|
|
||||||
$zip->addFile('../config/settings.json', 'settings/settings.json');
|
|
||||||
$zip->addFile('../config/folks.json', 'settings/folks.json');
|
|
||||||
$zip->addFile('../config/tags.json', 'settings/tags.json');
|
|
||||||
//save zip file
|
|
||||||
$zip->close();
|
|
||||||
|
|
||||||
//update settings file with latest back up date
|
|
||||||
$updated = Carbon::now();
|
|
||||||
Settings::updateGlobalData(
|
|
||||||
'last_backup',
|
|
||||||
$updated->format("Y-m-d\TH:i:sP")
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = ['message' => 'Backup created. THIS IS A SAFE SPACE!'];
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
223
brain/utility/Setup.inc.php
Normal file
223
brain/utility/Setup.inc.php
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
<?php
|
||||||
|
use function _\find;
|
||||||
|
class SetUp
|
||||||
|
{
|
||||||
|
public static function status()
|
||||||
|
{
|
||||||
|
if (file_exists("../config/settings.json")) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function init($body)
|
||||||
|
{
|
||||||
|
//grab template files
|
||||||
|
$newFolks = json_decode(
|
||||||
|
file_get_contents("../config/init/folks-template.json"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
$newSettings = json_decode(
|
||||||
|
file_get_contents("../config/init/settings-template.json"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
//get form values
|
||||||
|
//$body = $request->getParsedBody();
|
||||||
|
$handle = $body["new_member_handle"];
|
||||||
|
$email = $body["new_member_email"];
|
||||||
|
$pass = $body["new_member_pass"];
|
||||||
|
$title = $body["new_member_title"];
|
||||||
|
|
||||||
|
$now = new \Moment\Moment();
|
||||||
|
//setup folks config
|
||||||
|
$hash = password_hash($pass, PASSWORD_DEFAULT);
|
||||||
|
$newFolks[0]["id"] = 0;
|
||||||
|
$newFolks[0]["handle"] = $handle;
|
||||||
|
$newFolks[0]["email"] = $email;
|
||||||
|
$newFolks[0]["password"] = $hash;
|
||||||
|
$newFolks[0]["key"] = password_hash($email, PASSWORD_DEFAULT);
|
||||||
|
$newFolks[0]["secret"] = StringTools::randomString(12);
|
||||||
|
$newFolks[0]["role"] = "hnic";
|
||||||
|
$newFolks[0]["created"] = $now->format("Y-m-d\TH:i:sP");
|
||||||
|
$newFolks[0]["updated"] = $now->format("Y-m-d\TH:i:sP");
|
||||||
|
//set up settings config
|
||||||
|
$newSettings["global"]["title"] = $title;
|
||||||
|
|
||||||
|
//create index file
|
||||||
|
//$rightNow = $now->format("Y-m-d\TH:i:sP");
|
||||||
|
//var_dump($now->format("Y-m-d\TH:i:sP"));
|
||||||
|
$index = [
|
||||||
|
"id" => 1,
|
||||||
|
"uuid" => StringTools::createUUID(),
|
||||||
|
"title" => "FIRST!",
|
||||||
|
"feature" => "/assets/images/global/default-bg.jpg",
|
||||||
|
"path" => "content/pages/start",
|
||||||
|
"layout" => "index",
|
||||||
|
"tags" => "start, welcome",
|
||||||
|
"author" => $handle,
|
||||||
|
"created" => $now->format("Y-m-d\TH:i:sP"),
|
||||||
|
"updated" => $now->format("Y-m-d\TH:i:sP"),
|
||||||
|
"deleted" => "false",
|
||||||
|
"slug" => "first",
|
||||||
|
"menu" => "false",
|
||||||
|
"featured" => "false",
|
||||||
|
"published" => "true",
|
||||||
|
"content" =>
|
||||||
|
"# F**k Yes \n\nIf you're seeing this, you're up and running. NICE WORK!\n\nFrom here, feel free to start dropping pages to your heart's content.\n\nFor some tips about using Fipamo, check out the ![docs](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage)\n\nAll good? Feel free to edit this page to whatever you want!\n\nYOU'RE THE CAPTAIN NOW.",
|
||||||
|
];
|
||||||
|
|
||||||
|
$freshIndex = DocTools::objectToMD($index);
|
||||||
|
|
||||||
|
//once all files created, write down
|
||||||
|
|
||||||
|
DocTools::writeSettings("../config/settings.json", $newSettings);
|
||||||
|
DocTools::writeSettings("../config/folks.json", $newFolks);
|
||||||
|
DocTools::writeSettings("../config/tags.json", []);
|
||||||
|
DocTools::writePages(
|
||||||
|
"create",
|
||||||
|
"start",
|
||||||
|
"../content/pages/start/index.md",
|
||||||
|
$freshIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
//if there is an older session file, get rid of it
|
||||||
|
if (is_file("../content/.session")) {
|
||||||
|
unlink("../content/.session");
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = ["type" => "blogInitGood", "message" => "Site Created"];
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function restore($request)
|
||||||
|
{
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "Still working on it.",
|
||||||
|
];
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
|
||||||
|
$backup = $request->getUploadedFiles();
|
||||||
|
$file = $backup["backup-upload"];
|
||||||
|
$size = $file->getSize();
|
||||||
|
$name = $file->getClientFileName();
|
||||||
|
|
||||||
|
//park it so it can be read
|
||||||
|
$file->moveTo("../content" . "/" . $name);
|
||||||
|
|
||||||
|
//open it and get files to verify user
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
if ($zip->open("../content" . "/" . $name) === true) {
|
||||||
|
$folks = json_decode($zip->getFromName("settings/folks.json"), true);
|
||||||
|
$found = find($folks, ["handle" => $body["restore_member_handle"]]);
|
||||||
|
|
||||||
|
//if member is found in back up, check pass
|
||||||
|
if ($found) {
|
||||||
|
if (password_verify($body["restore_member_pass"], $found["password"])) {
|
||||||
|
//backup verified, restore site
|
||||||
|
|
||||||
|
//set new secret key for older folks configs
|
||||||
|
$newFolks = [];
|
||||||
|
if (!isset($found["secret"])) {
|
||||||
|
$found["secret"] = StringTools::randomString(12);
|
||||||
|
}
|
||||||
|
array_push($newFolks, $found);
|
||||||
|
//dump files in folder
|
||||||
|
$zip->extractTo("../content");
|
||||||
|
|
||||||
|
//move to appropriate spots
|
||||||
|
/*
|
||||||
|
rename(
|
||||||
|
"../content/settings/settings.json",
|
||||||
|
"../config/settings.json"
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//load up old config file
|
||||||
|
$newConfig = json_decode(
|
||||||
|
file_get_contents("../content/settings/settings.json"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
//check for key, add if not there
|
||||||
|
if (!isset($newConfig["global"]["externalAPI"])) {
|
||||||
|
$newConfig["global"]["externalAPI"] = "false";
|
||||||
|
}
|
||||||
|
//write new config file
|
||||||
|
DocTools::writeSettings("../config/settings.json", $newConfig);
|
||||||
|
|
||||||
|
//rename("../content/settings/folks.json", "../config/folks.json");
|
||||||
|
DocTools::writeSettings("../config/folks.json", $newFolks);
|
||||||
|
|
||||||
|
rename("../content/settings/tags.json", "../config/tags.json");
|
||||||
|
|
||||||
|
//images path for blog and user
|
||||||
|
$blogImagePath = "../public/assets/images/blog";
|
||||||
|
$userImagePath = "../public/assets/images/user";
|
||||||
|
|
||||||
|
//check to see if image dirs are empty, if not chill
|
||||||
|
if ($globs = glob($blogImagePath . "/*")) {
|
||||||
|
//directory not empty, relax
|
||||||
|
} else {
|
||||||
|
rename("../content/public/assets/images/blog", $blogImagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($globs = glob($userImagePath . "/*")) {
|
||||||
|
//directory not empty, relax
|
||||||
|
} else {
|
||||||
|
rename("../content/public/assets/images/user", $userImagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
rename("../content/content/pages/", "../content/pages");
|
||||||
|
|
||||||
|
//legacy check for old file structure
|
||||||
|
if (is_file("../content/pages/index.md")) {
|
||||||
|
if (!is_dir("../content/pages/start")) {
|
||||||
|
//Directory does not exist, so lets create it.
|
||||||
|
mkdir("../content/pages/start", 0755, true);
|
||||||
|
//move start page to appropriate spot
|
||||||
|
rename(
|
||||||
|
"../content/pages/index.md",
|
||||||
|
"../content/pages/start/index.md"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//chill
|
||||||
|
}
|
||||||
|
|
||||||
|
//clean up
|
||||||
|
|
||||||
|
DocTools::deleteFolder("../content/settings");
|
||||||
|
DocTools::deleteFolder("../content/public");
|
||||||
|
DocTools::deleteFolder("../content/content");
|
||||||
|
$result = [
|
||||||
|
"type" => "requestGood",
|
||||||
|
"message" => "Site Restored! Redirecting",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "Check that password, champ.",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "No member found by that name, hoss",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
$zipPath = "../content/" . $name;
|
||||||
|
//trash zip when done
|
||||||
|
unlink($zipPath);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "Could not open backup. RATS!",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,230 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\utility;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
use function _\find;
|
|
||||||
|
|
||||||
class SetUp
|
|
||||||
{
|
|
||||||
public static function status()
|
|
||||||
{
|
|
||||||
if (file_exists('../config/settings.json')) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function init($body)
|
|
||||||
{
|
|
||||||
//grab template files
|
|
||||||
$newFolks = json_decode(
|
|
||||||
file_get_contents('../config/init/folks-template.json'),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
$newSettings = json_decode(
|
|
||||||
file_get_contents('../config/init/settings-template.json'),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
//get form values
|
|
||||||
//$body = $request->getParsedBody();
|
|
||||||
$handle = $body['new_member_handle'];
|
|
||||||
$email = $body['new_member_email'];
|
|
||||||
$pass = $body['new_member_pass'];
|
|
||||||
$title = $body['new_member_title'];
|
|
||||||
|
|
||||||
$now = Carbon::now();
|
|
||||||
//setup folks config
|
|
||||||
$hash = password_hash($pass, PASSWORD_DEFAULT);
|
|
||||||
$newFolks[0]['id'] = 0;
|
|
||||||
$newFolks[0]['handle'] = $handle;
|
|
||||||
$newFolks[0]['email'] = $email;
|
|
||||||
$newFolks[0]['password'] = $hash;
|
|
||||||
$newFolks[0]['key'] = password_hash($email, PASSWORD_DEFAULT);
|
|
||||||
$newFolks[0]['secret'] = StringTools::randomString(12);
|
|
||||||
$newFolks[0]['role'] = 'hnic';
|
|
||||||
$newFolks[0]['created'] = $now->format("Y-m-d\TH:i:sP");
|
|
||||||
$newFolks[0]['updated'] = $now->format("Y-m-d\TH:i:sP");
|
|
||||||
//set up settings config
|
|
||||||
$newSettings['global']['title'] = $title;
|
|
||||||
|
|
||||||
//create index file
|
|
||||||
//$rightNow = $now->format("Y-m-d\TH:i:sP");
|
|
||||||
//var_dump($now->format("Y-m-d\TH:i:sP"));
|
|
||||||
$index = [
|
|
||||||
'id' => 1,
|
|
||||||
'uuid' => StringTools::createUUID(),
|
|
||||||
'title' => 'FIRST!',
|
|
||||||
'imageList' => '/assets/images/global/default-bg.jpg',
|
|
||||||
'fileList' => '',
|
|
||||||
'path' => 'content/pages/start',
|
|
||||||
'layout' => 'index',
|
|
||||||
'tags' => 'start, welcome',
|
|
||||||
'author' => $handle,
|
|
||||||
'created' => $now->format("Y-m-d\TH:i:sP"),
|
|
||||||
'updated' => $now->format("Y-m-d\TH:i:sP"),
|
|
||||||
'deleted' => 'false',
|
|
||||||
'slug' => 'first',
|
|
||||||
'menu' => 'false',
|
|
||||||
'featured' => 'false',
|
|
||||||
'published' => 'true',
|
|
||||||
'content' => "# F**k Yes \n\nIf you're seeing this, you're up and running. NICE WORK!\n\nFrom here, feel free to start dropping pages to your heart's content.\n\nFor some tips about using Fipamo, check out the ![docs](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage)\n\nAll good? Feel free to edit this page to whatever you want!\n\nYOU'RE THE CAPTAIN NOW.",
|
|
||||||
];
|
|
||||||
|
|
||||||
$freshIndex = DocTools::objectToMD($index);
|
|
||||||
|
|
||||||
//once all files created, write down
|
|
||||||
|
|
||||||
DocTools::writeSettings('../config/settings.json', $newSettings);
|
|
||||||
DocTools::writeSettings('../config/folks.json', $newFolks);
|
|
||||||
DocTools::writeSettings('../config/tags.json', []);
|
|
||||||
DocTools::writePages(
|
|
||||||
'create',
|
|
||||||
'start',
|
|
||||||
'../content/pages/start/index.md',
|
|
||||||
$freshIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
//if there is an older session file, get rid of it
|
|
||||||
if (is_file('../content/.session')) {
|
|
||||||
unlink('../content/.session');
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = ['type' => 'blogInitGood', 'message' => 'Site Created'];
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function restore($request)
|
|
||||||
{
|
|
||||||
$result = [
|
|
||||||
'type' => 'requestLame',
|
|
||||||
'message' => 'Still working on it.',
|
|
||||||
];
|
|
||||||
$body = $request->getParsedBody();
|
|
||||||
|
|
||||||
$backup = $request->getUploadedFiles();
|
|
||||||
$file = $backup['backup-upload'];
|
|
||||||
//NOTE: If this fails check 'post_max_size' in php.ini
|
|
||||||
$size = $file->getSize();
|
|
||||||
$name = $file->getClientFileName();
|
|
||||||
|
|
||||||
//park it so it can be read
|
|
||||||
$file->moveTo('../content' . '/' . $name);
|
|
||||||
|
|
||||||
//open it and get files to verify user
|
|
||||||
$zip = new \ZipArchive();
|
|
||||||
if ($zip->open('../content' . '/' . $name) === true) {
|
|
||||||
$folks = json_decode($zip->getFromName('settings/folks.json'), true);
|
|
||||||
$found = find($folks, ['handle' => $body['restore_member_handle']]);
|
|
||||||
|
|
||||||
//if member is found in back up, check pass
|
|
||||||
if ($found) {
|
|
||||||
if (password_verify($body['restore_member_pass'], $found['password'])) {
|
|
||||||
//backup verified, restore site
|
|
||||||
|
|
||||||
//set new secret key for older folks configs
|
|
||||||
$newFolks = [];
|
|
||||||
if (!isset($found['secret'])) {
|
|
||||||
$found['secret'] = StringTools::randomString(12);
|
|
||||||
}
|
|
||||||
array_push($newFolks, $found);
|
|
||||||
//dump files in folder
|
|
||||||
$zip->extractTo('../content');
|
|
||||||
|
|
||||||
//move to appropriate spots
|
|
||||||
/*
|
|
||||||
rename(
|
|
||||||
"../content/settings/settings.json",
|
|
||||||
"../config/settings.json"
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
//load up old config file
|
|
||||||
$newConfig = json_decode(
|
|
||||||
file_get_contents('../content/settings/settings.json'),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
//check for key, add if not there
|
|
||||||
if (!isset($newConfig['global']['externalAPI'])) {
|
|
||||||
$newConfig['global']['externalAPI'] = 'false';
|
|
||||||
}
|
|
||||||
//write new config file
|
|
||||||
DocTools::writeSettings('../config/settings.json', $newConfig);
|
|
||||||
|
|
||||||
//rename("../content/settings/folks.json", "../config/folks.json");
|
|
||||||
DocTools::writeSettings('../config/folks.json', $newFolks);
|
|
||||||
|
|
||||||
rename('../content/settings/tags.json', '../config/tags.json');
|
|
||||||
|
|
||||||
//images path for blog and user
|
|
||||||
$blogImagePath = '../public/assets/images/blog';
|
|
||||||
$userImagePath = '../public/assets/images/user';
|
|
||||||
|
|
||||||
//check to see if image dirs are empty, if not chill
|
|
||||||
if ($globs = glob($blogImagePath . '/*')) {
|
|
||||||
//directory not empty, relax
|
|
||||||
} else {
|
|
||||||
rename('../content/public/assets/images/blog', $blogImagePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($globs = glob($userImagePath . '/*')) {
|
|
||||||
//directory not empty, relax
|
|
||||||
} else {
|
|
||||||
rename('../content/public/assets/images/user', $userImagePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
rename('../content/content/pages/', '../content/pages');
|
|
||||||
|
|
||||||
//legacy check for old file structure
|
|
||||||
if (is_file('../content/pages/index.md')) {
|
|
||||||
if (!is_dir('../content/pages/start')) {
|
|
||||||
//Directory does not exist, so lets create it.
|
|
||||||
mkdir('../content/pages/start', 0755, true);
|
|
||||||
//move start page to appropriate spot
|
|
||||||
rename(
|
|
||||||
'../content/pages/index.md',
|
|
||||||
'../content/pages/start/index.md'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//chill
|
|
||||||
}
|
|
||||||
|
|
||||||
//clean up
|
|
||||||
|
|
||||||
DocTools::deleteFolder('../content/settings');
|
|
||||||
DocTools::deleteFolder('../content/public');
|
|
||||||
DocTools::deleteFolder('../content/content');
|
|
||||||
$result = [
|
|
||||||
'type' => 'requestGood',
|
|
||||||
'message' => 'Site Restored! Redirecting',
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'type' => 'requestLame',
|
|
||||||
'message' => 'Check that password, champ.',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'type' => 'requestLame',
|
|
||||||
'message' => 'No member found by that name, hoss',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$zip->close();
|
|
||||||
$zipPath = '../content/' . $name;
|
|
||||||
//trash zip when done
|
|
||||||
unlink($zipPath);
|
|
||||||
} else {
|
|
||||||
$result = [
|
|
||||||
'type' => 'requestLame',
|
|
||||||
'message' => 'Could not open backup. RATS!',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
232
brain/utility/Sorting.inc.php
Normal file
232
brain/utility/Sorting.inc.php
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
<?php
|
||||||
|
use Mni\FrontYAML\Parser;
|
||||||
|
use function _\find;
|
||||||
|
use function _\filter;
|
||||||
|
|
||||||
|
class Sorting
|
||||||
|
{
|
||||||
|
private static $_tags = [];
|
||||||
|
private static $_archive = [];
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function tags()
|
||||||
|
{
|
||||||
|
$pages = (new Book("../content/pages"))->getContents();
|
||||||
|
foreach ($pages as $page) {
|
||||||
|
$temp = [];
|
||||||
|
$temp = explode(",", $page["tags"]);
|
||||||
|
foreach ($temp as $tag) {
|
||||||
|
$label = trim($tag);
|
||||||
|
if (!find(self::$_tags, ["tag_name" => $label])) {
|
||||||
|
array_push(self::$_tags, [
|
||||||
|
"tag_name" => $label,
|
||||||
|
"slug" => StringTools::safeString($label),
|
||||||
|
"pages" => self::tagPages($label, $pages),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$_tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function tagPages($tag, $pages)
|
||||||
|
{
|
||||||
|
$tagged = [];
|
||||||
|
foreach ($pages as $page) {
|
||||||
|
if (strpos($page["tags"], $tag) !== false) {
|
||||||
|
array_push($tagged, [
|
||||||
|
"title" => $page["title"],
|
||||||
|
"slug" => $page["slug"],
|
||||||
|
"path" => $page["path"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tagged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function archive()
|
||||||
|
{
|
||||||
|
$pages = (new Book("../content/pages"))->getContents();
|
||||||
|
$years = [];
|
||||||
|
$archive = [];
|
||||||
|
foreach ($pages as $page) {
|
||||||
|
//$year = date("Y", date($page["rawCreated"]));
|
||||||
|
$date = explode("/", $page["path"]);
|
||||||
|
//echo $page["title"] . " : " . $year . "\n";
|
||||||
|
if (!find($years, ["year" => trim($date[0])])) {
|
||||||
|
$findPages = filter($pages, ["createdYear" => trim($date[0])]);
|
||||||
|
//var_dump($findPages);
|
||||||
|
array_push($years, [
|
||||||
|
"year" => trim($date[0]),
|
||||||
|
"count" => count($findPages),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($years as $year) {
|
||||||
|
$sorted = [];
|
||||||
|
$filtered = filter($pages, ["createdYear" => $year["year"]]);
|
||||||
|
|
||||||
|
foreach ($filtered as $obj) {
|
||||||
|
$month = date("m", date($obj["rawCreated"]));
|
||||||
|
if (!find($sorted, ["month" => $month])) {
|
||||||
|
$perMonth = filter($pages, [
|
||||||
|
"path" => $year["year"] . "/" . $month,
|
||||||
|
"deleted" => false,
|
||||||
|
"published" => true,
|
||||||
|
"layout" => "page",
|
||||||
|
]);
|
||||||
|
array_push($sorted, [
|
||||||
|
"month" => $month,
|
||||||
|
"full_month" => date("F", date($obj["rawCreated"])),
|
||||||
|
"count" => count($perMonth),
|
||||||
|
"pages" => $perMonth,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_push(self::$_archive, [
|
||||||
|
"year" => $year["year"],
|
||||||
|
"year_data" => $sorted,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return self::$_archive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function page($page)
|
||||||
|
{
|
||||||
|
$config = new Settings();
|
||||||
|
$settings = $config->getSettings();
|
||||||
|
$pageOption = [];
|
||||||
|
|
||||||
|
$pageInfo = [
|
||||||
|
"keywords" => isset($settings["global"]["keywords"])
|
||||||
|
? $settings["global"]["keywords"]
|
||||||
|
: "fipamo, blog, jamstack, php, markdown, js",
|
||||||
|
"description" => $settings["global"]["descriptions"],
|
||||||
|
"image" =>
|
||||||
|
$settings["global"]["base_url"] . $settings["global"]["background"],
|
||||||
|
"baseURL" => $settings["global"]["base_url"],
|
||||||
|
];
|
||||||
|
|
||||||
|
$taglist = explode(",", $page["tags"]);
|
||||||
|
$tags = [];
|
||||||
|
foreach ($taglist as $tag) {
|
||||||
|
$label = trim($tag);
|
||||||
|
array_push($tags, [
|
||||||
|
"label" => $label . " ",
|
||||||
|
"slug" => StringTools::safeString($label),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$meta = [
|
||||||
|
"who" => $page["author"],
|
||||||
|
"when" => $page["created"],
|
||||||
|
"tags" => $tags,
|
||||||
|
];
|
||||||
|
|
||||||
|
//render markdown content and clean it
|
||||||
|
$parser = new Parser();
|
||||||
|
$rendered = $parser->parse($page["content"]);
|
||||||
|
$sanitizer = HtmlSanitizer\Sanitizer::create([
|
||||||
|
"extensions" => ["basic", "image", "list", "code"],
|
||||||
|
"tags" => [
|
||||||
|
"img" => [
|
||||||
|
"allowed_attributes" => ["src", "alt", "title", "class"],
|
||||||
|
"allowed_hosts" => null,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$preclean = $sanitizer->sanitize($rendered->getContent());
|
||||||
|
|
||||||
|
//just clean renderd string for now, Sanitize doesn't like relative img urls
|
||||||
|
//so another option is needed
|
||||||
|
$cleaned = strip_tags($rendered->getContent(), [
|
||||||
|
"a",
|
||||||
|
"br",
|
||||||
|
"p",
|
||||||
|
"strong",
|
||||||
|
"br",
|
||||||
|
"img",
|
||||||
|
"iframe",
|
||||||
|
"ul",
|
||||||
|
"li",
|
||||||
|
"i",
|
||||||
|
"em",
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"pre",
|
||||||
|
"code",
|
||||||
|
]);
|
||||||
|
//$cleaned = preg_replace('/(?:\r\n|[\r\n]){2,}/', "\n\n", $cleaned);
|
||||||
|
//$cleaned = html_entity_decode($cleaned, ENT_QUOTES, "UTF-8");
|
||||||
|
|
||||||
|
//if page feature isn't empty, replace page info meta image
|
||||||
|
if ($page["feature"] != "" || $page["feature"] != null) {
|
||||||
|
$pageInfo["image"] = $pageInfo["baseURL"] . $page["feature"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($page["layout"] == "index") {
|
||||||
|
//$template = $this->theme . "/index.twig";
|
||||||
|
//$location = "../public/index.html";
|
||||||
|
//$dir = null;
|
||||||
|
|
||||||
|
$recent = [];
|
||||||
|
$featured = [];
|
||||||
|
$limit = 4;
|
||||||
|
$pages = (new Book("../content/pages"))->getContents();
|
||||||
|
foreach ($pages as $item) {
|
||||||
|
//TODO: Move page data organization to render to utility class
|
||||||
|
if (!$item["deleted"] && $item["published"]) {
|
||||||
|
if (count($recent) < $limit) {
|
||||||
|
array_push($recent, [
|
||||||
|
"path" => $item["path"],
|
||||||
|
"slug" => $item["slug"],
|
||||||
|
"title" => $item["title"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item["featured"] == true) {
|
||||||
|
if (count($featured) < $limit) {
|
||||||
|
array_push($featured, [
|
||||||
|
"path" => $item["path"],
|
||||||
|
"slug" => $item["slug"],
|
||||||
|
"title" => $item["title"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => $page["title"],
|
||||||
|
"background" => $page["feature"],
|
||||||
|
"content" => $cleaned,
|
||||||
|
"meta" => $meta,
|
||||||
|
"recent" => $recent,
|
||||||
|
"featured" => $featured,
|
||||||
|
"info" => $pageInfo,
|
||||||
|
"menu" => $settings["menu"],
|
||||||
|
"dynamicRender" => $settings["global"]["dynamicRender"],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
//$template = $this->theme . "/page.twig";
|
||||||
|
//$location = "../public/" . $page["path"] . "/" . $page["slug"] . ".html";
|
||||||
|
//$dir = "../public/" . $page["path"];
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => $page["title"],
|
||||||
|
"background" => $page["feature"],
|
||||||
|
"content" => $cleaned,
|
||||||
|
"meta" => $meta,
|
||||||
|
"info" => $pageInfo,
|
||||||
|
"menu" => $settings["menu"],
|
||||||
|
"dynamicRender" => $settings["global"]["dynamicRender"],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $pageOptions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,269 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\utility;
|
|
||||||
|
|
||||||
use brain\data\Book;
|
|
||||||
use brain\data\Settings;
|
|
||||||
use Mni\FrontYAML\Parser;
|
|
||||||
|
|
||||||
use function _\filter;
|
|
||||||
use function _\find;
|
|
||||||
|
|
||||||
class Sorting
|
|
||||||
{
|
|
||||||
private static $p_tags = [];
|
|
||||||
private static $p_archive = [];
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function tags()
|
|
||||||
{
|
|
||||||
$pages = (new Book('../content/pages'))->getContents();
|
|
||||||
foreach ($pages as $page) {
|
|
||||||
$temp = [];
|
|
||||||
if (isset($page['tags'])) {
|
|
||||||
$temp = explode(',', $page['tags']);
|
|
||||||
foreach ($temp as $tag) {
|
|
||||||
$label = trim($tag);
|
|
||||||
if (!find(self::$p_tags, ['tag_name' => $label])) {
|
|
||||||
array_push(self::$p_tags, [
|
|
||||||
'tag_name' => $label,
|
|
||||||
'slug' => StringTools::safeString($label),
|
|
||||||
'pages' => self::tagPages($label, $pages),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$p_tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function tagPages($tag, $pages)
|
|
||||||
{
|
|
||||||
$tagged = [];
|
|
||||||
foreach ($pages as $page) {
|
|
||||||
if (isset($page['tags'])) {
|
|
||||||
if (strpos($page['tags'], $tag) !== false) {
|
|
||||||
array_push($tagged, [
|
|
||||||
'title' => $page['title'],
|
|
||||||
'slug' => $page['slug'],
|
|
||||||
'path' => $page['path'],
|
|
||||||
'feature' => $page['feature'],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tagged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function archive()
|
|
||||||
{
|
|
||||||
$pages = (new Book('../content/pages'))->getContents();
|
|
||||||
$years = [];
|
|
||||||
$archive = [];
|
|
||||||
foreach ($pages as $page) {
|
|
||||||
// $year = date("Y", date($page["rawCreated"]));
|
|
||||||
$date = explode('/', $page['path']);
|
|
||||||
// echo $page["title"] . " : " . $year . "\n";
|
|
||||||
if (!find($years, ['year' => trim($date[0])])) {
|
|
||||||
$findPages = filter($pages, ['createdYear' => trim($date[0])]);
|
|
||||||
// var_dump($findPages);
|
|
||||||
array_push(
|
|
||||||
$years,
|
|
||||||
[
|
|
||||||
'year' => trim($date[0]),
|
|
||||||
'count' => count($findPages),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($years as $year) {
|
|
||||||
$sorted = [];
|
|
||||||
$filtered = filter($pages, ['createdYear' => $year['year']]);
|
|
||||||
|
|
||||||
foreach ($filtered as $obj) {
|
|
||||||
$month = date('m', date($obj['rawCreated']));
|
|
||||||
if (!find($sorted, ['month' => $month])) {
|
|
||||||
$perMonth = filter(
|
|
||||||
$pages,
|
|
||||||
[
|
|
||||||
'path' => $year['year'] . '/' . $month,
|
|
||||||
'deleted' => false,
|
|
||||||
'published' => true,
|
|
||||||
'layout' => 'page',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
array_push($sorted, [
|
|
||||||
'month' => $month,
|
|
||||||
'full_month' => date('F', date($obj['rawCreated'])),
|
|
||||||
'count' => count($perMonth),
|
|
||||||
'pages' => $perMonth,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
array_push(self::$p_archive, [
|
|
||||||
'year' => $year['year'],
|
|
||||||
'year_data' => $sorted,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$p_archive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function page($page)
|
|
||||||
{
|
|
||||||
$config = new Settings();
|
|
||||||
$settings = $config->getSettings();
|
|
||||||
$pageOption = [];
|
|
||||||
|
|
||||||
$pageInfo = [
|
|
||||||
'keywords' => isset($settings['global']['keywords'])
|
|
||||||
? $settings['global']['keywords']
|
|
||||||
: 'fipamo, blog, jamstack, php, markdown, js',
|
|
||||||
'description' => $settings['global']['descriptions'],
|
|
||||||
'image' => $settings['global']['base_url'] . $settings['global']['background'],
|
|
||||||
'baseURL' => $settings['global']['base_url'],
|
|
||||||
];
|
|
||||||
$tags = [];
|
|
||||||
if (isset($page['tags'])) {
|
|
||||||
$taglist = explode(',', $page['tags']);
|
|
||||||
foreach ($taglist as $tag) {
|
|
||||||
$label = trim($tag);
|
|
||||||
array_push($tags, [
|
|
||||||
'label' => $label . ' ',
|
|
||||||
'slug' => StringTools::safeString($label),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$meta = [
|
|
||||||
'who' => $page['author'],
|
|
||||||
'when' => $page['created'],
|
|
||||||
'tags' => $tags,
|
|
||||||
];
|
|
||||||
|
|
||||||
// render markdown content and clean it
|
|
||||||
$parser = new Parser();
|
|
||||||
$rendered = $parser->parse($page['content']);
|
|
||||||
$sanitizer = \HtmlSanitizer\Sanitizer::create([
|
|
||||||
'extensions' => ['basic', 'image', 'list', 'code'],
|
|
||||||
'tags' => [
|
|
||||||
'img' => [
|
|
||||||
'allowed_attributes' => ['src', 'alt', 'title', 'class'],
|
|
||||||
'allowed_hosts' => null,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$preclean = $sanitizer->sanitize($rendered->getContent());
|
|
||||||
|
|
||||||
// just clean renderd string for now, Sanitize doesn't like relative img urls
|
|
||||||
// so another option is needed
|
|
||||||
$cleaned = strip_tags($rendered->getContent(), [
|
|
||||||
'a',
|
|
||||||
'br',
|
|
||||||
'p',
|
|
||||||
'strong',
|
|
||||||
'br',
|
|
||||||
'img',
|
|
||||||
'iframe',
|
|
||||||
'ul',
|
|
||||||
'li',
|
|
||||||
'i',
|
|
||||||
'em',
|
|
||||||
'h1',
|
|
||||||
'h2',
|
|
||||||
'h3',
|
|
||||||
'pre',
|
|
||||||
'code',
|
|
||||||
]);
|
|
||||||
|
|
||||||
// if page feature isn't empty, find image from list and set it as background image
|
|
||||||
// if it is empty, just use global background
|
|
||||||
if ($page['feature'] != '' || $page['feature'] != null) {
|
|
||||||
$media = explode(',', $page['feature']);
|
|
||||||
$set = false;
|
|
||||||
foreach ($media as $file) {
|
|
||||||
$item = trim($file);
|
|
||||||
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
|
||||||
|
|
||||||
if ($ext != 'mp4' && !$set) {
|
|
||||||
$pageInfo['image'] = $pageInfo['baseURL'] . $item;
|
|
||||||
$set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($page['layout'] == 'index') {
|
|
||||||
// $template = $this->theme . "/index.twig";
|
|
||||||
// $location = "../public/index.html";
|
|
||||||
// $dir = null;
|
|
||||||
|
|
||||||
$recent = [];
|
|
||||||
$featured = [];
|
|
||||||
$limit = 4;
|
|
||||||
$pages = (new Book())->getContents();
|
|
||||||
foreach ($pages as $item) {
|
|
||||||
if (!$item['deleted'] &&
|
|
||||||
$item['published'] &&
|
|
||||||
$item['menu'] != 'true'
|
|
||||||
) {
|
|
||||||
if (count($recent) < $limit) {
|
|
||||||
array_push($recent, [
|
|
||||||
'path' => $item['path'],
|
|
||||||
'slug' => $item['slug'],
|
|
||||||
'title' => $item['title'],
|
|
||||||
'feature' => $item['feature'],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($item['featured'] == true) {
|
|
||||||
if (count($featured) < $limit) {
|
|
||||||
array_push($featured, [
|
|
||||||
'path' => $item['path'],
|
|
||||||
'slug' => $item['slug'],
|
|
||||||
'title' => $item['title'],
|
|
||||||
'feature' => $item['feature'],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => $page['title'],
|
|
||||||
'background' => $page['feature'],
|
|
||||||
'content' => $page['html'], // $cleaned,
|
|
||||||
'meta' => $meta,
|
|
||||||
'recent' => $recent,
|
|
||||||
'featured' => $featured,
|
|
||||||
'info' => $pageInfo,
|
|
||||||
'menu' => $settings['menu'],
|
|
||||||
'dynamicRender' => $settings['global']['dynamicRender'],
|
|
||||||
'media' => $page['media'],
|
|
||||||
'files' => $page['docs'],
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
// $template = $this->theme . "/page.twig";
|
|
||||||
// $location = "../public/" . $page["path"] . "/" . $page["slug"] . ".html";
|
|
||||||
// $dir = "../public/" . $page["path"];
|
|
||||||
$pageOptions = [
|
|
||||||
'title' => $page['title'],
|
|
||||||
'background' => $page['feature'],
|
|
||||||
'content' => $page['html'], // $cleaned,
|
|
||||||
'meta' => $meta,
|
|
||||||
'info' => $pageInfo,
|
|
||||||
'menu' => $settings['menu'],
|
|
||||||
'dynamicRender' => $settings['global']['dynamicRender'],
|
|
||||||
'media' => $page['media'],
|
|
||||||
'files' => $page['docs'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pageOptions;
|
|
||||||
}
|
|
||||||
}
|
|
130
brain/utility/StringTools.inc.php
Normal file
130
brain/utility/StringTools.inc.php
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
<?php
|
||||||
|
use ReallySimpleJWT\Token;
|
||||||
|
use ReallySimpleJWT\Exception\BuildException;
|
||||||
|
use Mni\FrontYAML\Parser;
|
||||||
|
//include "brain/data/Auth.inc.php";
|
||||||
|
|
||||||
|
class StringTools
|
||||||
|
{
|
||||||
|
public static function createUUID()
|
||||||
|
{
|
||||||
|
if (function_exists("com_create_guid") === true) {
|
||||||
|
return trim(com_create_guid(), "{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
"%04X%04X-%04X-%04X-%04X-%04X%04X%04X",
|
||||||
|
mt_rand(0, 65535),
|
||||||
|
mt_rand(0, 65535),
|
||||||
|
mt_rand(0, 65535),
|
||||||
|
mt_rand(16384, 20479),
|
||||||
|
mt_rand(32768, 49151),
|
||||||
|
mt_rand(0, 65535),
|
||||||
|
mt_rand(0, 65535),
|
||||||
|
mt_rand(0, 65535)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function sanitizeContent($entry)
|
||||||
|
{
|
||||||
|
$parser = new Parser();
|
||||||
|
$rendered = $parser->parse($entry);
|
||||||
|
$sanitizer = HtmlSanitizer\Sanitizer::create([
|
||||||
|
"extensions" => ["basic", "image", "list", "code"],
|
||||||
|
"tags" => [
|
||||||
|
"img" => [
|
||||||
|
"allowed_attributes" => ["src", "alt", "title", "class"],
|
||||||
|
"allowed_hosts" => null,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$preclean = $sanitizer->sanitize($rendered->getContent());
|
||||||
|
|
||||||
|
$cleaned = strip_tags($rendered->getContent(), [
|
||||||
|
"a",
|
||||||
|
"br",
|
||||||
|
"p",
|
||||||
|
"strong",
|
||||||
|
"br",
|
||||||
|
"img",
|
||||||
|
"iframe",
|
||||||
|
"ul",
|
||||||
|
"li",
|
||||||
|
"i",
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"pre",
|
||||||
|
"code",
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $cleaned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function safeString($string)
|
||||||
|
{
|
||||||
|
return strtolower(
|
||||||
|
trim(
|
||||||
|
preg_replace(
|
||||||
|
"~[^0-9a-z]+~i",
|
||||||
|
"_",
|
||||||
|
html_entity_decode(
|
||||||
|
preg_replace(
|
||||||
|
"~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i",
|
||||||
|
'$1',
|
||||||
|
htmlentities($string, ENT_QUOTES, "UTF-8")
|
||||||
|
),
|
||||||
|
ENT_QUOTES,
|
||||||
|
"UTF-8"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
"-"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function randomString(int $length)
|
||||||
|
{
|
||||||
|
$alphanum =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
$special = '*&!@%^#$';
|
||||||
|
$alphabet = $alphanum . $special;
|
||||||
|
$random = openssl_random_pseudo_bytes($length);
|
||||||
|
$alphabet_length = strlen($alphabet);
|
||||||
|
$string = "";
|
||||||
|
for ($i = 0; $i < $length; ++$i) {
|
||||||
|
$string .= $alphabet[ord($random[$i]) % $alphabet_length];
|
||||||
|
}
|
||||||
|
|
||||||
|
//secret needs to be a valid token
|
||||||
|
if ($length == 12) {
|
||||||
|
try {
|
||||||
|
$secret = Token::create(12, $string, time() + 3600, "localhost");
|
||||||
|
return $string;
|
||||||
|
} catch (BuildException $e) {
|
||||||
|
//bad secret, so try agiain
|
||||||
|
//echo "BAD STRING";
|
||||||
|
return self::randomString(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Token::validate($key, $string)) {
|
||||||
|
return $string;
|
||||||
|
} else {
|
||||||
|
return self::randomString(12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function checkSpecial($string)
|
||||||
|
{
|
||||||
|
$specials = ["*", "&", "!", "@", "%", "^", "#", "$"];
|
||||||
|
$valid = false;
|
||||||
|
foreach ($specials as $item) {
|
||||||
|
if (strpos($string, $item)) {
|
||||||
|
return $valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,131 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace brain\utility;
|
|
||||||
|
|
||||||
use ReallySimpleJWT\Token;
|
|
||||||
use ReallySimpleJWT\Exception\BuildException;
|
|
||||||
use Mni\FrontYAML\Parser;
|
|
||||||
|
|
||||||
class StringTools
|
|
||||||
{
|
|
||||||
public static function createUUID()
|
|
||||||
{
|
|
||||||
if (function_exists('com_create_guid') === true) {
|
|
||||||
return trim(com_create_guid(), '{}');
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf(
|
|
||||||
'%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
|
|
||||||
mt_rand(0, 65535),
|
|
||||||
mt_rand(0, 65535),
|
|
||||||
mt_rand(0, 65535),
|
|
||||||
mt_rand(16384, 20479),
|
|
||||||
mt_rand(32768, 49151),
|
|
||||||
mt_rand(0, 65535),
|
|
||||||
mt_rand(0, 65535),
|
|
||||||
mt_rand(0, 65535)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function sanitizeContent($entry)
|
|
||||||
{
|
|
||||||
$parser = new Parser();
|
|
||||||
$rendered = $parser->parse($entry);
|
|
||||||
$sanitizer = HtmlSanitizer\Sanitizer::create([
|
|
||||||
'extensions' => ['basic', 'image', 'list', 'code'],
|
|
||||||
'tags' => [
|
|
||||||
'img' => [
|
|
||||||
'allowed_attributes' => ['src', 'alt', 'title', 'class'],
|
|
||||||
'allowed_hosts' => null,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$preclean = $sanitizer->sanitize($rendered->getContent());
|
|
||||||
|
|
||||||
$cleaned = strip_tags($rendered->getContent(), [
|
|
||||||
'a',
|
|
||||||
'br',
|
|
||||||
'p',
|
|
||||||
'strong',
|
|
||||||
'br',
|
|
||||||
'img',
|
|
||||||
'iframe',
|
|
||||||
'ul',
|
|
||||||
'li',
|
|
||||||
'i',
|
|
||||||
'h1',
|
|
||||||
'h2',
|
|
||||||
'h3',
|
|
||||||
'pre',
|
|
||||||
'code',
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $cleaned;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function safeString($string)
|
|
||||||
{
|
|
||||||
return strtolower(
|
|
||||||
trim(
|
|
||||||
preg_replace(
|
|
||||||
'~[^0-9a-z]+~i',
|
|
||||||
'_',
|
|
||||||
html_entity_decode(
|
|
||||||
preg_replace(
|
|
||||||
'~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i',
|
|
||||||
'$1',
|
|
||||||
htmlentities($string, ENT_QUOTES, 'UTF-8')
|
|
||||||
),
|
|
||||||
ENT_QUOTES,
|
|
||||||
'UTF-8'
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'-'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function randomString(int $length)
|
|
||||||
{
|
|
||||||
$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
||||||
$special = '*&!@%^#$';
|
|
||||||
$alphabet = $alphanum . $special;
|
|
||||||
$random = openssl_random_pseudo_bytes($length);
|
|
||||||
$alphabet_length = strlen($alphabet);
|
|
||||||
$string = '';
|
|
||||||
for ($i = 0; $i < $length; ++$i) {
|
|
||||||
$string .= $alphabet[ord($random[$i]) % $alphabet_length];
|
|
||||||
}
|
|
||||||
|
|
||||||
//secret needs to be a valid token
|
|
||||||
if ($length == 12) {
|
|
||||||
try {
|
|
||||||
$secret = Token::create(12, $string, time() + 3600, 'localhost');
|
|
||||||
return $string;
|
|
||||||
} catch (BuildException $e) {
|
|
||||||
//bad secret, so try agiain
|
|
||||||
//echo "BAD STRING";
|
|
||||||
return self::randomString(12);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Token::validate($key, $string)) {
|
|
||||||
return $string;
|
|
||||||
} else {
|
|
||||||
return self::randomString(12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function checkSpecial($string)
|
|
||||||
{
|
|
||||||
$specials = ['*', '&', '!', '@', '%', '^', '#', '$'];
|
|
||||||
$valid = false;
|
|
||||||
foreach ($specials as $item) {
|
|
||||||
if (strpos($string, $item)) {
|
|
||||||
return $valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $valid;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,8 +2,6 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="theme-color" content="#FFFFFF"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>
|
<title>
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -12,38 +10,51 @@
|
||||||
{% block stylesheets %}{% endblock %}
|
{% block stylesheets %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="notifications" class="notifications">
|
||||||
|
<div id="notifyMessage" class="notifyMessage">
|
||||||
|
<div id="notify-good" class="notify-icon">
|
||||||
|
<svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-emoji-flirt"/></svg>
|
||||||
|
</div>
|
||||||
|
<div id="notify-lame" class="notify-icon">
|
||||||
|
<svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-emoji-sad"/></svg>
|
||||||
|
</div>
|
||||||
|
<div id="notify-working" class="notify-icon">
|
||||||
|
<svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-cog"/></svg>
|
||||||
|
</div>
|
||||||
|
<p id="message-text"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="main-content" class="main-container">
|
||||||
|
<section id="dash-index-content">
|
||||||
{% if status %}
|
{% if status %}
|
||||||
<header>
|
<header id="header">
|
||||||
|
<div id="wrapper">
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
<nav role="top-nav">
|
<div id="left">
|
||||||
<div role="nav-left">
|
|
||||||
<a href="/dashboard"><img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/></a>
|
<a href="/dashboard"><img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/></a>
|
||||||
</div>
|
</div>
|
||||||
<div role="title">
|
<div id="right">
|
||||||
<h1>{{ title }}</h1>
|
|
||||||
</div>
|
|
||||||
<div role="nav-right">
|
|
||||||
{% if status %}
|
{% if status %}
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
{{ include("dash/partials/navigation.twig") }}
|
{{ include("dash/partials/navigation.twig") }}
|
||||||
{% endapply %}
|
{% endapply %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
|
||||||
<div role="notify">
|
|
||||||
{% apply spaceless %}
|
|
||||||
{{ include("dash/partials/notifications.twig") }}
|
|
||||||
{% endapply %}
|
{% endapply %}
|
||||||
</div>
|
</div>
|
||||||
{% endapply %}
|
|
||||||
{% endif %}
|
|
||||||
</header>
|
</header>
|
||||||
<main>
|
{% endif %}
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
{% block mainContent %}{% endblock %}
|
{% block mainContent %}{% endblock %}
|
||||||
{% endapply %}
|
{% endapply %}
|
||||||
</main>
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<footer></footer>
|
<footer></footer>
|
||||||
<script type="module" src="/assets/scripts/dash.js"></script>
|
{% block javascripts %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -5,65 +5,103 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=vdthg">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfdfa">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
<section role="book-index-header">
|
<div id="post-index">
|
||||||
<div role="book-index-header-left">
|
<div id="post-index-wrapper">
|
||||||
{{ filter }}
|
<div id="post-index-header">
|
||||||
Pages
|
<div id="post-index-header-left">
|
||||||
|
{{ filter }} Pages
|
||||||
</div>
|
</div>
|
||||||
<div role="book-index-header-right">
|
<div id="post-index-header-right">
|
||||||
<a href="/dashboard/pages/all" title="view all pages">
|
<a href="/dashboard/pages/all" title="view all pages">
|
||||||
<button>
|
<button>
|
||||||
<i class="ti ti-clipboard-list"></i>
|
<svg >
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-archive"/>
|
||||||
|
</svg>
|
||||||
{{ stats['all'] }}
|
{{ stats['all'] }}
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
<a href="/dashboard/pages/published" title="view publised pages">
|
<a href="/dashboard/pages/published" title="view publised pages">
|
||||||
<button>
|
<button>
|
||||||
<i class="ti ti-clipboard-check"></i>
|
<svg >
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
|
||||||
|
</svg>
|
||||||
{{ stats['published'] }}
|
{{ stats['published'] }}
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
<a href="/dashboard/pages/deleted" title="view deleted pages">
|
<a href="/dashboard/pages/deleted" title="view deleted pages">
|
||||||
<button>
|
<button>
|
||||||
<i class="ti ti-clipboard-off"></i>
|
<svg >
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-circle-with-cross"/>
|
||||||
|
</svg>
|
||||||
{{ stats['deleted'] }}
|
{{ stats['deleted'] }}
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</div>
|
||||||
<section role="book-index-pages">
|
|
||||||
|
</div>
|
||||||
|
<div id="posts-list">
|
||||||
{% for page in pages %}
|
{% for page in pages %}
|
||||||
{% if page.media[0].type == 'mp4' %}
|
|
||||||
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="page-link">
|
|
||||||
<div class="page-video">
|
|
||||||
<video class="post-video" loop muted autoplay>
|
|
||||||
<source src="{{ page.media[0].file }}" type="video/mp4">
|
|
||||||
|
|
||||||
Sorry, your browser doesn't support embedded videos.
|
|
||||||
</video>
|
|
||||||
<div id="meta">
|
|
||||||
{{ include("dash/partials/recent-meta.twig") }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="page-link" href="/dashboard/page/edit/{{ page.uuid }}">
|
<a class="page-link" href="/dashboard/page/edit/{{ page.uuid }}">
|
||||||
<div class="page-bg" style="background: url({{ page.media[0].file }}) no-repeat center center / cover #fc6399">
|
<div class="page-bg" style="background: url({{ page.feature }}) no-repeat center center / cover">
|
||||||
|
<label>
|
||||||
|
{{ page.title }}
|
||||||
|
</label>
|
||||||
<div id="meta">
|
<div id="meta">
|
||||||
{{ include("dash/partials/recent-meta.twig") }}
|
|
||||||
|
<div id="options">
|
||||||
|
{% if page.menu == 'true' %}
|
||||||
|
{% set menu = "true" %}
|
||||||
|
{% else %}
|
||||||
|
{% set menu = "false" %}
|
||||||
|
{% endif %}
|
||||||
|
{% if page.published == 'true' %}
|
||||||
|
{% set published = "true" %}
|
||||||
|
{% else %}
|
||||||
|
{% set published = "false" %}
|
||||||
|
{% endif %}
|
||||||
|
{% if page.featured == 'true' %}
|
||||||
|
{% set featured = "true" %}
|
||||||
|
{% else %}
|
||||||
|
{% set featured = "false" %}
|
||||||
|
{% endif %}
|
||||||
|
<div id="option-left">
|
||||||
|
|
||||||
|
<button data-active="{{ menu }}">
|
||||||
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-add-to-list"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button data-active="{{ published }}">
|
||||||
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button data-active="{{ featured }}">
|
||||||
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-star"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="option-right">
|
||||||
|
<span>
|
||||||
|
{{ page.updated }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if numOfPages > 1 %}
|
{% if numOfPages > 1 %}
|
||||||
<div role="paginate">
|
<div class="paginate">
|
||||||
<a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['prevPage'] }}">
|
<a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['prevPage'] }}">
|
||||||
<i class="ti ti-square-arrow-left"></i>
|
<svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-chevron-left"/></svg>
|
||||||
</a>
|
</a>
|
||||||
<span class="count">
|
<span class="count">
|
||||||
{{ currentPage }}
|
{{ currentPage }}
|
||||||
|
@ -71,10 +109,16 @@
|
||||||
{{ numOfPages }}
|
{{ numOfPages }}
|
||||||
</span>
|
</span>
|
||||||
<a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['nextPage'] }}">
|
<a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['nextPage'] }}">
|
||||||
<i class="ti ti-square-arrow-right"></i>
|
<svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-chevron-right"/></svg>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</section>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="/assets/scripts/dash.min.js" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,16 +0,0 @@
|
||||||
<div>
|
|
||||||
<a href="/dashboard">
|
|
||||||
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<form id="init-restore" method="POST">
|
|
||||||
<input type="text" name="restore_member_handle" id="restore_member_handle" placeholder="handle"/><input type="password" name="restore_member_pass" id="restore_member_pass" placeholder="password"/>
|
|
||||||
<div>
|
|
||||||
<label>Grab your backup zip</label>
|
|
||||||
<input id="backup-upload" type="file" name="backup-upload" placeholder="Backup Zip"/>
|
|
||||||
</div>
|
|
||||||
<br/><br/>
|
|
||||||
<button id="blog-restore" data-action='blog-restore' type='submit'>RESTORE</button>
|
|
||||||
<br/><br/>
|
|
||||||
<button class="init-option" id="init-switch-fresh">OR INSTALL FROM SCRATCH</button>
|
|
||||||
</form>
|
|
|
@ -1,15 +0,0 @@
|
||||||
<div>
|
|
||||||
<a href="/dashboard">
|
|
||||||
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<form id="init-form" method="POST" onsubmit="return false;">
|
|
||||||
<input type="text" name="new_member_handle" id="new_member_handle" placeholder="handle"/>
|
|
||||||
<input type="text" name="new_member_email" id="new_member_email" placeholder="email"/>
|
|
||||||
<input type="text" name="new_member_pass" id="new_member_pass" placeholder="password"/>
|
|
||||||
<input type="text" name="new_member_pass2" id="new_member_pass2" placeholder="password confirm"/>
|
|
||||||
<input type="text" name="new_member_title" id="new_member_title" placeholder="title"/>
|
|
||||||
<button id="init-blog" data-action='blog-init' type='submit'>SET UP YOUR SITE</button>
|
|
||||||
<br/><br/>
|
|
||||||
<button class="init-option" id="init-switch-restore">RESTORE FROM BACKUP</button>
|
|
||||||
</form>
|
|
|
@ -1,13 +1,13 @@
|
||||||
<section role="login">
|
<div id="dash-login">
|
||||||
<div>
|
<div id="dash-form" class="dash-form">
|
||||||
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
||||||
</div>
|
<form id="login" class='login' name="login" action="/@/dashboard/login" method="POST">
|
||||||
<form id="login" class='login' name="login" method="POST" onsubmit="return false;">
|
<input type="text" name="handle" class="form-control" placeholder="Handle" required ">
|
||||||
<input type="text" name="handle" class="form-control" placeholder="Handle" required/>
|
<input type="password" name="password" class="form-control" placeholder="Password" required">
|
||||||
<input type="password" name="password" class="form-control" placeholder="Password" required/>
|
<button id="login-btn" class='login-btn' type='submit'>
|
||||||
<button id="login-btn" class='login-btn'>
|
|
||||||
ID, PLEASE
|
ID, PLEASE
|
||||||
</button>
|
</button><br /><br />
|
||||||
<a href="/dashboard/reset-password">?</a>
|
<a href="/dashboard/reset-password"> Forgot Password?</a>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</div>
|
||||||
|
</div>
|
|
@ -1,21 +0,0 @@
|
||||||
<div>
|
|
||||||
<a href="/dashboard">
|
|
||||||
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<form id="reset" class='login' name="reset" action="/dashboard/login" method="POST">
|
|
||||||
|
|
||||||
<input type="password" id="new_password" name="new_password" class="form-control" placeholder="New Password" required/>
|
|
||||||
<input type="password" id="new_password2" name="new_password2" class="form-control" placeholder="New Password Confirm" required">
|
|
||||||
<input type="password" id="secret" name="secret" class="form-control" placeholder="Account Secret" required/>
|
|
||||||
<button id="reset-btn" class='login-btn' type='submit'>
|
|
||||||
RESET PASSWORD
|
|
||||||
</button><br/>
|
|
||||||
<p>
|
|
||||||
Use this to get your secret to verify it's you. If your email is set up, the secret will be sent there. If not, the form will be updated automatically(but please set up your email, once you reset your password).
|
|
||||||
</p>
|
|
||||||
<input type="text" id="email" name="email" class="form-control" placeholder="email to verify" required/>
|
|
||||||
<button id="get-secret-btn" class='login-btn' type='submit'>
|
|
||||||
VERIFY EMAIL
|
|
||||||
</button><br/><br/>
|
|
||||||
</form>
|
|
|
@ -5,20 +5,44 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfa">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
<article role="site-restore">
|
<div id="dash-index">
|
||||||
<section role="restore-fresh">
|
<div id="dash-index-wrapper">
|
||||||
{% apply spaceless %}
|
<div id="dash-init" class="dash-init">
|
||||||
{{ include("dash/forms/init-fresh.twig") }}
|
<form id="init-form">
|
||||||
{% endapply %}
|
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
||||||
</section>
|
<input type="text" name="new_member_handle" id="new_member_handle" placeholder="handle"/>
|
||||||
<section role="restore-backup">
|
<input type="text" name="new_member_email" id="new_member_email" placeholder="email"/>
|
||||||
{% apply spaceless %}
|
<input type="text" name="new_member_pass" id="new_member_pass" placeholder="password"/>
|
||||||
{{ include("dash/forms/init-backup.twig") }}
|
<input type="text" name="new_member_pass2" id="new_member_pass2" placeholder="password confirm"/>
|
||||||
{% endapply %}
|
<input type="text" name="new_member_title" id="new_member_title" placeholder="title"/>
|
||||||
</section>
|
<button id="init-blog" data-action='blog-init' type='submit'>SET UP YOUR SITE</button>
|
||||||
</article>
|
<br /><br />
|
||||||
|
<button class="init-option" id="init-switch-restore">RESTORE FROM BACKUP</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="dash-restore" class="dash-restore">
|
||||||
|
<form id="init-restore">
|
||||||
|
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
||||||
|
<input type="text" name="restore_member_handle" id="restore_member_handle" placeholder="handle"/><input type="password" name="restore_member_pass" id="restore_member_pass" placeholder="password"/>
|
||||||
|
<div>
|
||||||
|
<label>Grab your backup zip</label>
|
||||||
|
<input id="backup-upload" type="file" name="backup-upload" placeholder="Backup Zip"/>
|
||||||
|
</div>
|
||||||
|
<br /><br />
|
||||||
|
<button id="blog-restore" data-action='blog-restore' type='submit'>RESTORE</button>
|
||||||
|
<br /><br />
|
||||||
|
<button class="init-option" id="init-switch-fresh">OR INSTALL FROM SCRATCH</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="/assets/scripts/dash.min.js" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -5,26 +5,39 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=sdsdsds">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=sdsdsds">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
<article role="navigation">
|
<div id="nav-index">
|
||||||
<section id="nav-items">
|
<div id="nav-index-wrapper">
|
||||||
|
<div id="nav-pages">
|
||||||
{% for item in menu %}
|
{% for item in menu %}
|
||||||
<div id="{{item.id}}" class="nav-item" data-slug="{{item.slug}}" data-uuid="{{item.uuid}}" data-path="{{item.path}}">
|
<div id="{{item.id}}" class="nav-item" data-slug="{{item.slug}}" data-uuid="{{item.uuid}}" data-path="{{item.path}}">
|
||||||
<i class="ti ti-arrows-move-vertical"></i>
|
<svg id="item-arrows">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-select-arrows"/>
|
||||||
|
</svg>
|
||||||
<label>{{item.title}}</label>
|
<label>{{item.title}}</label>
|
||||||
<div id="nav-btns">
|
<div id="nav-btns">
|
||||||
<button id="edit-item" class="nav-btn" data-id="{{item.uuid}}" title="edit page">
|
<button id="edit-item" class="nav-btn" data-id="{{item.uuid}}" title="edit page">
|
||||||
<i class="ti ti-edit"></i>
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-edit"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button id="remove-item" class="nav-btn" data-uuid="{{item.uuid}}" data-id="{{item.id}}" title="delete from menu">
|
<button id="remove-item" class="nav-btn" data-uuid="{{item.uuid}}" data-id="{{item.id}}" title="delete from menu">
|
||||||
<i class="ti ti-x"></i>
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-cross"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
</div>
|
||||||
</article>
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="/assets/scripts/dash.min.js" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -9,12 +9,10 @@
|
||||||
{% set slug = page['slug'] %}
|
{% set slug = page['slug'] %}
|
||||||
{% set layout = page['layout'] %}
|
{% set layout = page['layout'] %}
|
||||||
{% set feature = page['feature'] %}
|
{% set feature = page['feature'] %}
|
||||||
|
{% set _title = page['title'] %}
|
||||||
{% set tags = page['tags'] %}
|
{% set tags = page['tags'] %}
|
||||||
{% set content = page['content'] %}
|
{% set content = page['content'] %}
|
||||||
{% set date = page['created'] %}
|
{% set date = page['created'] %}
|
||||||
{% set updated = page['updated'] %}
|
|
||||||
{% set media = page['media'] %}
|
|
||||||
{% set files = page['docs'] %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set id = '' %}
|
{% set id = '' %}
|
||||||
{% set uuid = '' %}
|
{% set uuid = '' %}
|
||||||
|
@ -25,9 +23,6 @@
|
||||||
{% set tags = '' %}
|
{% set tags = '' %}
|
||||||
{% set content = '' %}
|
{% set content = '' %}
|
||||||
{% set date = '' %}
|
{% set date = '' %}
|
||||||
{% set updated = '' %}
|
|
||||||
{% set media = '' %}
|
|
||||||
{% set files = '' %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
|
@ -35,129 +30,44 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=vdthg">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfdfdf">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
<section data-index="{{ id }}" data-uuid="{{ uuid }}" data-slug="{{ slug }}" data-layout="{{ layout }}" role="file-manager">
|
<div id="post-edit-index" data-index="{{ id }}" data-uuid="{{ uuid }}" data-slug="{{ slug }}" data-layout="{{ layout }}">
|
||||||
|
<div id="post-edit-index-wrapper">
|
||||||
|
<div id="post-feature">
|
||||||
{% if page['feature'] == null %}
|
{% if page['feature'] == null %}
|
||||||
<div role="file-drop">
|
<div id="featured-image-drop">
|
||||||
<label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label>
|
DRAG AND DROP IMAGE OR <label for="featured-image-upload">CLICK TO CHOSE</label>
|
||||||
</div>
|
</div>
|
||||||
<label role="list-title">IMAGES AND VIDEO</label>
|
|
||||||
<div role="page-images-list"></div>
|
|
||||||
<label role="list-title">FILES</label>
|
|
||||||
<div role="page-files-list"></div>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div role="file-drop">
|
<div id="featured-new-image-btn">
|
||||||
<label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label>
|
<button id="new-feature-upload">
|
||||||
</div>
|
<svg id="new-feature-upload" viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-image-inverted"/></svg>
|
||||||
<label role="list-title">IMAGES AND VIDEO</label>
|
|
||||||
<div role="page-images-list">
|
|
||||||
{% if media|length > 1 %}
|
|
||||||
{% for item in media %}
|
|
||||||
{% set fileName = item.file|split('/') %}
|
|
||||||
{% if item.type == "mp4" %}
|
|
||||||
|
|
||||||
<div id="{{ loop.index0 }}" class="video-item" data-source="{{ item.file }}">
|
|
||||||
<video>
|
|
||||||
<source src="{{ item.file }}"/>
|
|
||||||
</video>
|
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">
|
|
||||||
<i class="ti ti-x"></i>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
<div id="featured-image-drop">
|
||||||
<div id="{{ loop.index0 }}" class="img-item" data-source="{{ item.file }}" style="background: url({{ item.file }}) no-repeat center center / cover">
|
<img id="featured-image" src="{{ feature }}"/>
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">
|
|
||||||
<i class="ti ti-x"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% if media[0] != '' %}
|
|
||||||
{% set fileName = media[0].file|split('/') %}
|
|
||||||
{% if media[0].type == "mp4" %}
|
|
||||||
<div id="0" class="video-item" data-source="{{ media[0].file }}">
|
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">X</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<div id="0" class="img-item" data-source="{{ media[0].file }}" style="background: url({{ media[0].file }}) no-repeat center center / cover">
|
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">
|
|
||||||
<i class="ti ti-x"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<label role="list-title">FILES</label>
|
|
||||||
<div role="page-files-list">
|
|
||||||
{% if files|length > 1 %}
|
|
||||||
{% for item in files %}
|
|
||||||
{% set fileName = item.file|split('/') %}
|
|
||||||
{% if item.type == "mp3" %}
|
|
||||||
<div id="{{ loop.index0 }}" class="audio-item" data-source="{{ item.file }}">
|
|
||||||
<audio controls>
|
|
||||||
<source src="{{ item.file }}"/>
|
|
||||||
</audio>
|
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">
|
|
||||||
<i class="ti ti-x"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div id="{{ loop.index0 }}" class="file-item" data-source="{{ item.file }}">
|
|
||||||
<a href="{{ item.file }}" target="_blank">{{ fileName[6] }}"</a>
|
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">
|
|
||||||
<i class="ti ti-x"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% if files[0] != '' %}
|
|
||||||
{% set fileName = files[0].file|split('/') %}
|
|
||||||
{% if files[0].type == "mp3" %}
|
|
||||||
<div id="0" class="audio-item" data-source="{{ files[0].file }}">
|
|
||||||
<audio controls>
|
|
||||||
<source src="{{ files[0].file }}"/>
|
|
||||||
</audio>
|
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">
|
|
||||||
<i class="ti ti-x"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div id="0" class="file-item" data-source="{{ files[0].file }}">
|
|
||||||
<a href="{{ item.file }}" target="_blank">{{ fileName[6] }}"</a>
|
|
||||||
<button id="{{ loop.index0 }}" class="media-remove">
|
|
||||||
<i class="ti ti-x"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
<div id="post-header">
|
||||||
</section>
|
<div id="post-header-wrapper" class="columns">
|
||||||
<section role="page-meta">
|
<div id="post-title" class="column">
|
||||||
<div role="page-meta-wrapper">
|
<label>TITLE</label>
|
||||||
<div role="page-title">
|
<textarea id="post_title" type="text" name="post_title" class="post-edit" placeholder="TITLE">
|
||||||
<strong>TITLE</strong>
|
{{- _title -}}
|
||||||
<textarea id="post-title-text" type="text" name="post-title-text" class="post-edit" placeholder="TITLE">{{ title }}</textarea>
|
</textarea>
|
||||||
</div>
|
<label>CREATED</label>
|
||||||
<div role="page-tags">
|
<br/>
|
||||||
<strong>TAGS</strong>
|
<span id="post-date" type="text">
|
||||||
<textarea id="post-tags" type="text" name="post-tags" class="form-control" placeholder="tags [comma seperated]">{{ tags }}</textarea>
|
{{ date }}
|
||||||
</div>
|
</span>
|
||||||
<div role="page-layouts">
|
<div id="layouts">
|
||||||
<strong>LAYOUTS</strong>
|
<label>LAYOUTS</label>
|
||||||
<select id="page-templates">
|
<select id="page-templates">
|
||||||
{% for view in views %}
|
{% for view in views %}
|
||||||
{% if view == page['layout'] %}
|
{% if view == page['layout'] %}
|
||||||
|
@ -169,38 +79,34 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div role="page-options">
|
</div>
|
||||||
<strong>OPTIONS</strong>
|
<div id="post-meta" class="column">
|
||||||
|
<label>TAGS</label>
|
||||||
|
<textarea id="post_tags" type="text" name="post_tags" class="form-control" placeholder="tags [comma seperated]">
|
||||||
|
{{- tags -}}
|
||||||
|
</textarea>
|
||||||
|
<label>OPTIONS</label>
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
{{ include("dash/partials/options.twig") }}
|
{{ include("dash/partials/options.twig") }}
|
||||||
{% endapply %}
|
{% endapply %}
|
||||||
</div>
|
<input id="featured-image-upload" type="file" name="featured-image-upload"/>
|
||||||
<div role="page-updated">
|
|
||||||
<strong>UPDATED</strong>
|
|
||||||
<span id="post-date" type="text">
|
|
||||||
{{ updated }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div role="page-created">
|
|
||||||
<strong>CREATED</strong>
|
|
||||||
<span id="post-date" type="text">
|
|
||||||
{{ date }}
|
|
||||||
</span>
|
|
||||||
<input id="page-files-upload" type="file" name="page-files-upload" multiple/>
|
|
||||||
<input id="post-image-upload" type="file" name="post-image-upload"/>
|
<input id="post-image-upload" type="file" name="post-image-upload"/>
|
||||||
<input id="form_token" name="token" type="hidden" value="{{ token }}"></div>
|
<input id="form_token" name="token" type="hidden" value="{{ token }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
<section role="text-editor">
|
<div id="edit-post">
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
{{ include("dash/partials/editor.twig") }}
|
{{ include("dash/partials/editor.twig") }}
|
||||||
{% endapply %}
|
{% endapply %}
|
||||||
<div role="edit-post-wrapper">
|
<div id="edit-post-wrapper">
|
||||||
<textarea id="edit" spellcheck="false" class="language-md">{{ content }}</textarea>
|
<pre><code id="edit-post-text" contenteditable="true"> {{- content -}}</code></pre>
|
||||||
<pre id="highlight">
|
</div>
|
||||||
<code id="highlight-content" class="language-md"></code>
|
</div>
|
||||||
</pre>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="/assets/scripts/dash.min.js" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,38 +1,45 @@
|
||||||
<div role="text-editor-control">
|
<div id="edit-control">
|
||||||
<button id="edit-bold" class="content-editor-btn-text editor-button" title="bold">
|
<button id="edit-bold" class="content-editor-btn-text editor-button" title="bold">B</button>
|
||||||
<i id="edit-bold" class="ti ti-bold"></i>
|
<button id="edit-italic" class="content-editor-btn-text editor-button" title="italic">I</button>
|
||||||
</button>
|
<button id="edit-strikethrough" class="content-editor-btn-text editor-button" title="strikethrough">D</button>
|
||||||
<button id="edit-italic" class="content-editor-btn-text editor-button" title="italic">
|
|
||||||
<i id="edit-italic" class="ti ti-italic"></i>
|
|
||||||
</button>
|
|
||||||
<button id="edit-strikethrough" class="content-editor-btn-text editor-button" title="strikethrough">
|
|
||||||
<i id="edit-strikethrough" class="ti ti-strikethrough"></i>
|
|
||||||
</button>
|
|
||||||
<button id="edit-link" class="content-editor-btn-icon editor-button" title="insert link">
|
<button id="edit-link" class="content-editor-btn-icon editor-button" title="insert link">
|
||||||
<i id="edit-link" class="ti ti-link"></i>
|
<svg id="edit-link" viewbox="0 0 20 20" class="icons">
|
||||||
</button>
|
<use id="edit-link" xlink:href="/assets/images/global/sprite.svg#entypo-link"/>
|
||||||
<button id="edit-header1" class="content-editor-btn-text editor-button" title="header 1">
|
</svg>
|
||||||
<i id="edit-header1" class="ti ti-h-1"></i>
|
|
||||||
</button>
|
|
||||||
<button id="edit-header2" class="content-editor-btn-text editor-button" title="header 2">
|
|
||||||
<i id="edit-header2" class="ti ti-h-2"></i>
|
|
||||||
</button>
|
|
||||||
<button id="edit-header3" class="content-editor-btn-text editor-button" title="header 3">
|
|
||||||
<i id="edit-header3" class="ti ti-h-3"></i>
|
|
||||||
</button>
|
</button>
|
||||||
|
<button id="edit-header1" class="content-editor-btn-text editor-button" title="header 1">H1</button>
|
||||||
|
<button id="edit-header2" class="content-editor-btn-text editor-button" title="header 2">H2</button>
|
||||||
|
<button id="edit-header3" class="content-editor-btn-text editor-button" title="header 3">H3</button>
|
||||||
<button id="edit-image" class="content-editor-btn-icon editor-button" title="insert image">
|
<button id="edit-image" class="content-editor-btn-icon editor-button" title="insert image">
|
||||||
<i id="edit-image" class="ti ti-photo"></i>
|
<svg id="edit-image" viewbox="0 0 20 20" class="icons">
|
||||||
|
<use id="edit-image" xlink:href="/assets/images/global/sprite.svg#entypo-image"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
{% if mode == "edit" %}
|
{% if mode == "edit" %}
|
||||||
<button id="edit-update" class="post-sumbit-btn submit-start editor-button" data-action='blog-update' data-id="{{ page['uuid'] }} type='submit' title=" bold">
|
<button id="edit-update" class="post-sumbit-btn submit-start editor-button" data-action='blog-update' data-id=page.id type='submit' title="bold">
|
||||||
<i id="edit-update" class="ti ti-device-floppy"></i>
|
<svg id="submit-update" viewbox="0 0 20 20" class="icons">
|
||||||
|
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-save" data-action='blog-update' data-id="{{ page['uuid'] }}"/>
|
||||||
|
</svg>
|
||||||
|
<svg id="submit-good" class="icon-hide" viewbox="0 0 20 20" class="icons">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-thumbs-up"/>
|
||||||
|
</svg>
|
||||||
|
<svg id="submit-error" class="icon-hide" viewbox="0 0 20 20" class="icons">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-thumbs-down"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button id="edit-delete" class="content-editor-btn-icon editor-button submit-delete" for="post-delete" title='delete post'>
|
<button id="edit-delete" class="content-editor-btn-icon editor-button submit-delete" for="post-delete" title='delete post'>
|
||||||
<i id="edit-delete" class="ti ti-x"></i>
|
<svg id="edit-delete" viewbox="0 0 20 20" class="icons">
|
||||||
|
<use id="edit-delete" xlink:href="/assets/images/global/sprite.svg#entypo-cross"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button id="edit-save" class="post-sumbit-btn submit-start editor-button" data-action='blog-add' type='submit'>
|
<button id="edit-save" class="post-sumbit-btn submit-start editor-button" data-action='blog-add' type='submit'>
|
||||||
<i id="edit-save" class="ti ti-file-plus"></i>
|
<svg id="submit-save" viewbox="0 0 20 20" class="icons">
|
||||||
|
<use id="submit-save" xlink:href="/assets/images/global/sprite.svg#entypo-plus"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
|
@ -1,30 +1,81 @@
|
||||||
<section role="index-header">
|
<div id="dash-recent">
|
||||||
<div role="index-header-left">
|
<div id="recent-list">
|
||||||
<h1>Recent</h1>
|
<div class="recent-header">
|
||||||
|
<div class="index-header-left">
|
||||||
|
Recent
|
||||||
</div>
|
</div>
|
||||||
<div role="index-header-right"></div>
|
<div class="index-header-right">
|
||||||
</section>
|
<a href='/dashboard/pages' title="view pages">
|
||||||
<section role="index-recent-pages">
|
<button>
|
||||||
|
<svg class="page-link">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-archive"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href='/dashboard/page/add/new' title="add new page">
|
||||||
|
<button>
|
||||||
|
<svg class="page-link">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-plus"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
{% if data["entryCount"] != 0 %}
|
{% if data["entryCount"] != 0 %}
|
||||||
{% for page in data['pages'] %}
|
{% for page in data['pages'] %}
|
||||||
{% if page.media[0].type == 'mp4' %}
|
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-link" style="background: url({{ page.feature }}) no-repeat center center / cover">
|
||||||
|
<label>
|
||||||
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-video-link recent-link">
|
{{ page.title }}
|
||||||
{{ include("dash/partials/recent-meta.twig") }}
|
</label>
|
||||||
<video class="post-video" loop muted autoplay>
|
<div id="options">
|
||||||
<source src="{{ page.media[0].file }}" type="video/mp4">
|
{% if page.menu == 'true' %}
|
||||||
Sorry, your browser doesn't support embedded videos.
|
{% set menu = "true" %}
|
||||||
</video>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-link recent-link" style="background: url({{ page.media[0].file }}) no-repeat center center / cover #fc6399">
|
{% set menu = "false" %}
|
||||||
{{ include("dash/partials/recent-meta.twig") }}
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if page.published == 'true' %}
|
||||||
|
{% set published = "true" %}
|
||||||
|
{% else %}
|
||||||
|
{% set published = "false" %}
|
||||||
|
{% endif %}
|
||||||
|
{% if page.featured == 'true' %}
|
||||||
|
{% set featured = "true" %}
|
||||||
|
{% else %}
|
||||||
|
{% set featured = "false" %}
|
||||||
|
{% endif %}
|
||||||
|
<div id="option-left">
|
||||||
|
|
||||||
|
<button data-active="{{ menu }}">
|
||||||
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-add-to-list"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button data-active="{{ published }}">
|
||||||
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button data-active="{{ featured }}">
|
||||||
|
<svg>
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-star"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="option-right">
|
||||||
|
<span>
|
||||||
|
{{ page.updated }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
There are no pages
|
There are no pages
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</section>
|
</div>
|
||||||
|
</div>
|
|
@ -1,57 +1,23 @@
|
||||||
<div role="menu">
|
<div id="dash-menu">
|
||||||
{% if title == "Settings" %}
|
|
||||||
{% apply spaceless %}
|
|
||||||
{{ include("dash/partials/submenu_settings.twig") }}
|
|
||||||
{% endapply %}
|
|
||||||
{% elseif title=="Start" %}
|
|
||||||
{% apply spaceless %}
|
|
||||||
{{ include("dash/partials/submenu_start.twig") }}
|
|
||||||
{% endapply %}
|
|
||||||
{% endif %}
|
|
||||||
<a id="settings" href="/dashboard/settings" title="settings">
|
<a id="settings" href="/dashboard/settings" title="settings">
|
||||||
<button>
|
<button>
|
||||||
<i class="ti ti-home-cog"></i>
|
<svg class="menu">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-sound-mix"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a> .
|
||||||
<a id="navigation" href="/dashboard/navigation" title="edit navigation">
|
<a id="navigation" href="/dashboard/navigation" title="edit navigation">
|
||||||
<button>
|
<button>
|
||||||
<i class="ti ti-arrow-autofit-height"></i>
|
<svg class="menu">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-list"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a> .
|
||||||
<a id="navigation" href="/dashboard/logout" title="log out">
|
<a id="navigation" href="/dashboard/logout" title="log out">
|
||||||
<button>
|
<button>
|
||||||
<i class="ti ti-logout"></i>
|
<svg class="menu">
|
||||||
</button>
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-log-out"/>
|
||||||
</a>
|
</svg>
|
||||||
</div>
|
|
||||||
|
|
||||||
<button role="menu-toggle">
|
|
||||||
<i class="ti ti-menu-2"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div role="mobile-menu">
|
|
||||||
{% if title == "Settings" %}
|
|
||||||
{% apply spaceless %}
|
|
||||||
{{ include("dash/partials/submenu_settings.twig") }}
|
|
||||||
{% endapply %}
|
|
||||||
{% elseif title=="Start" %}
|
|
||||||
{% apply spaceless %}
|
|
||||||
{{ include("dash/partials/submenu_start.twig") }}
|
|
||||||
{% endapply %}
|
|
||||||
{% endif %}
|
|
||||||
<a id="settings" href="/dashboard/settings" title="settings">
|
|
||||||
<button>
|
|
||||||
<i class="ti ti-home-cog"></i>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
<a id="navigation" href="/dashboard/navigation" title="edit navigation">
|
|
||||||
<button>
|
|
||||||
<i class="ti ti-arrow-autofit-height"></i>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
<a id="navigation" href="/dashboard/logout" title="log out">
|
|
||||||
<button>
|
|
||||||
<i class="ti ti-logout"></i>
|
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
|
@ -1,10 +0,0 @@
|
||||||
<div role="notify-message">
|
|
||||||
<div role="notify-icons">
|
|
||||||
<i class="ti ti-mood-smile" role="notify-good"></i>
|
|
||||||
<i class="ti ti-mood-sad" role="notify-notgood"></i>
|
|
||||||
<i class="ti ti-settings" role="notify-working"></i>
|
|
||||||
</div>
|
|
||||||
<div role="notify-text">
|
|
||||||
<span role="response-text">Hey Hey</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -15,26 +15,28 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set published = 'false' %}
|
{% set published = 'false' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br>
|
|
||||||
|
<div id="post-options">
|
||||||
<button id="option-menu-pin" class="option-inactive post-option-btn" data-active="{{ menu }}" title='Pin to Menu'>
|
<button id="option-menu-pin" class="option-inactive post-option-btn" data-active="{{ menu }}" title='Pin to Menu'>
|
||||||
<svg id="option-page-icon" role="icon">
|
<svg id="option-page-icon" viewbox="0 0 20 20" class="icons">
|
||||||
<use id="option-page-icon" xlink:href="/assets/images/global/sprite.svg#entypo-add-to-list"/>
|
<use id="option-page-icon" xlink:href="/assets/images/global/sprite.svg#entypo-add-to-list"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button id="option-feature" class="option-inactive post-option-btn" data-active="{{ featured }}" title='Feature'>
|
<button id="option-feature" class="option-inactive post-option-btn" data-active="{{ featured }}" title='Feature'>
|
||||||
<svg id="option-feature-icon" role="icon">
|
<svg id="option-feature-icon" viewbox="0 0 20 20" class="icons">
|
||||||
<use id="option-feature-icon" xlink:href="/assets/images/global/sprite.svg#entypo-star"/>
|
<use id="option-feature-icon" xlink:href="/assets/images/global/sprite.svg#entypo-star"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button id="option-published" class="option-inactive post-option-btn" data-active="{{ published }}" title='Published'>
|
<button id="option-published" class="option-inactive post-option-btn" data-active="{{ published }}" title='Published'>
|
||||||
<svg id="option-published-icon" role="icon">
|
<svg id="option-published-icon" viewbox="0 0 20 20" class="icons">
|
||||||
<use id="option-published-icon" xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
|
<use id="option-published-icon" xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<a href="/dashboard/page/preview/{{ uuid }}" target="_blank">
|
<a href="/dashboard/page/preview/{{ uuid }}" target="_blank">
|
||||||
<button id="option-preview" class="option-inactive post-option-btn" data-active="false" title='preview page'>
|
<button id="option-preview" class="option-inactive post-option-btn" data-active="false" title='preview page'>
|
||||||
<svg id="option-preview-icon" role="icon">
|
<svg id="option-preview-icon" viewbox="0 0 20 20" class="icons">
|
||||||
<use id="option-preview-icon" xlink:href="/assets/images/global/sprite.svg#entypo-eye"/>
|
<use id="option-preview-icon" xlink:href="/assets/images/global/sprite.svg#entypo-eye"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
|
@ -1,37 +0,0 @@
|
||||||
{% if page.menu == 'true' %}
|
|
||||||
{% set menu = "true" %}
|
|
||||||
{% else %}
|
|
||||||
{% set menu = "false" %}
|
|
||||||
{% endif %}
|
|
||||||
{% if page.published == 'true' %}
|
|
||||||
{% set published = "true" %}
|
|
||||||
{% else %}
|
|
||||||
{% set published = "false" %}
|
|
||||||
{% endif %}
|
|
||||||
{% if page.featured == 'true' %}
|
|
||||||
{% set featured = "true" %}
|
|
||||||
{% else %}
|
|
||||||
{% set featured = "false" %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<aside>
|
|
||||||
<strong>
|
|
||||||
{{ page.updated }}
|
|
||||||
</strong>
|
|
||||||
<hr/>
|
|
||||||
<strong>
|
|
||||||
{{ page.title }}
|
|
||||||
</strong>
|
|
||||||
<hr/>
|
|
||||||
<button data-active="{{ menu }}">
|
|
||||||
<i class="ti ti-navigation"></i>
|
|
||||||
</button>
|
|
||||||
<button data-active="{{ published }}">
|
|
||||||
<i class="ti ti-world"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button data-active="{{ featured }}">
|
|
||||||
<i class="ti ti-star"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</aside>
|
|
|
@ -1,11 +0,0 @@
|
||||||
<div role="submenu">
|
|
||||||
<button id="save-toggle" title="save settings">
|
|
||||||
<i class="ti ti-device-floppy"></i>
|
|
||||||
</button>
|
|
||||||
<button id="publish-pages" title="publish site">
|
|
||||||
<i class="ti ti-world-upload"></i>
|
|
||||||
</button>
|
|
||||||
<button id="render-toggle" title="render on save toggle" data-render="{{ renderOnSave }}">
|
|
||||||
<i class="ti ti-circle-dashed"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<div role="submenu">
|
|
||||||
<a href='/dashboard/pages' title="view pages">
|
|
||||||
<button>
|
|
||||||
<i class="ti ti-book-2"></i>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
<a href='/dashboard/page/add/new' title="add new page">
|
|
||||||
<button>
|
|
||||||
<i class="ti ti-square-plus"></i>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
|
@ -5,14 +5,37 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfdfdf">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
<section role="password-reset">
|
<div id="dash-index">
|
||||||
{% apply spaceless %}
|
<div id="dash-index-wrapper">
|
||||||
{{ include("dash/forms/reset.twig") }}
|
<div id="dash-login">
|
||||||
{% endapply %}
|
<div id="dash-reset" class="dash-reset">
|
||||||
|
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
||||||
|
<form id="reset" class='login' name="reset" action="/@/dashboard/login" method="POST">
|
||||||
|
|
||||||
</section>
|
<input type="password" id="new_password"name="new_password" class="form-control" placeholder="New Password" required">
|
||||||
|
<input type="password" id="new_password2" name="new_password2" class="form-control" placeholder="New Password Confirm" required">
|
||||||
|
<input type="password" id="secret" name="secret" class="form-control" placeholder="Account Secret" required">
|
||||||
|
<button id="reset-btn" class='login-btn' type='submit'>
|
||||||
|
RESET PASSWORD
|
||||||
|
</button><br />
|
||||||
|
<p>
|
||||||
|
Use this to get your secret to verify it's you. If your email is set up, the secret will be sent there. If not, the form will be updated automatically(but please set up your email, once you reset your password).
|
||||||
|
</p>
|
||||||
|
<input type="text"id="email" name="email" class="form-control" placeholder="email to verify" required">
|
||||||
|
<button id="get-secret-btn" class='login-btn' type='submit'>
|
||||||
|
VERIFY EMAIL
|
||||||
|
</button><br /><br />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="/assets/scripts/dash.min.js" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -5,87 +5,117 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=cvnbm">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=cvvvb">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
<article role="settings">
|
<div id="settings-actions">
|
||||||
<section role="member-settings">
|
<div id="buttons">
|
||||||
<div role="member-avatar">
|
<button id="save-toggle" title="save settings">
|
||||||
<div role="avatar" style="background: url({{ member['avatar'] }} ) no-repeat center center / cover"></div>
|
<svg id="submit-update" class="icons">
|
||||||
|
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-save"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button id="publish-pages" title="publish site">
|
||||||
|
<svg id="submit-update" class="icons">
|
||||||
|
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-publish"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button id="render-toggle" title="render on save toggle" data-render="{{ renderOnSave }}">
|
||||||
|
<svg id="render-toggle-icon" class="icons">
|
||||||
|
<use xlink:href="/assets/images/global/sprite.svg#entypo-circular-graph"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="settings-index">
|
||||||
|
<div id="settings-index-wrapper">
|
||||||
|
<div id="member-settings">
|
||||||
|
<div id="member-images" class="columns">
|
||||||
|
<div class="column is-one-third">
|
||||||
|
<div id="member-avatar-drop">
|
||||||
|
<img id="avatar" src="{{member['avatar']}}" for="avatar-upload"/>
|
||||||
<input id="avatar-upload" type="file" name="avatar-upload" />
|
<input id="avatar-upload" type="file" name="avatar-upload" />
|
||||||
</div>
|
</div>
|
||||||
<div role="site-background">
|
</div>
|
||||||
<div role="background" style="background: url({{ background }} ) no-repeat center center / cover"></div>
|
<div class="column is-two-thirds">
|
||||||
|
<div id="site-background">
|
||||||
|
<img id="background" src="{{background}}" alt="image for site background" for="background-upload"/>
|
||||||
<input id="background-upload" type="file" name="backgrond-upload" />
|
<input id="background-upload" type="file" name="backgrond-upload" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="member-meta" class="columns">
|
||||||
|
<div class="column is-one-third">
|
||||||
<input type='text' name='handle' id='settings-handle' placeholder='handle' value="{{member['handle']}}" autofocus />
|
<input type='text' name='handle' id='settings-handle' placeholder='handle' value="{{member['handle']}}" autofocus />
|
||||||
<input type='text' name='email' id='settings-email' placeholder='email' value="{{member['email']}}" autofocus />
|
<input type='text' name='email' id='settings-email' placeholder='email' value="{{member['email']}}" autofocus />
|
||||||
|
</div>
|
||||||
|
<div class="column is-one-third">
|
||||||
<input type='text' name='base-url' id='settings-url' placeholder='url' value="{{baseUrl}}" autofocus />
|
<input type='text' name='base-url' id='settings-url' placeholder='url' value="{{baseUrl}}" autofocus />
|
||||||
<input type='text' name='base-title' id='settings-title' placeholder='site title' value="{{siteTitle}}" autofocus />
|
<input type='text' name='base-title' id='settings-title' placeholder='site title' value="{{siteTitle}}" autofocus />
|
||||||
|
</div>
|
||||||
|
<div class="column is-one-third">
|
||||||
<textarea id="settings-desc" type='text' name='settings_desc' class='settings-dec' placeholder='description stuff', autofocus>{{desc}}</textarea>
|
<textarea id="settings-desc" type='text' name='settings_desc' class='settings-dec' placeholder='description stuff', autofocus>{{desc}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<button id="create-backup">
|
|
||||||
<i class="ti ti-disc"></i>
|
|
||||||
<span>BACK UP YOUR SITE</span>
|
|
||||||
</button><br/>
|
|
||||||
{% if lastBackup != '' %}
|
|
||||||
LAST BACK UP<br/>
|
|
||||||
<a href="/api/v1/files">{{ lastBackup }}</a><br/>
|
|
||||||
{% else %}
|
|
||||||
<span>span No back ups. Frowny face.</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div role="features">
|
</div>
|
||||||
|
<div id="feature-settings">
|
||||||
|
<div id="features" class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div id="feature-api">
|
||||||
{% if apiStatus is defined and apiStatus == "true" %}
|
{% if apiStatus is defined and apiStatus == "true" %}
|
||||||
<button id="api-access-toggle" title="allow external api" data-enabled="true">
|
<button id="api-access-toggle" title="allow external api" data-enabled="true">
|
||||||
<i class="ti ti-phone-incoming"></i>
|
<svg id="api-access-toggle" class="icons">
|
||||||
<span id="api-status">API ACCESS ENABLED</span>
|
<use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<span id="api-status">EXTERNAL API ACCESS ENABLED</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button id="api-access-toggle" title="allow external api" data-enabled="false">
|
<button id="api-access-toggle" title="allow external api" data-enabled="false">
|
||||||
<i class="ti ti-phone-incoming"></i>
|
<svg id="api-access-toggle" class="icons">
|
||||||
<span id="api-status">API ACCESS NOT ENABLED</span>
|
<use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<span id="api-status">EXTERNAL API ACCESS NOT ENABLED</span>
|
||||||
{% endif %}
|
|
||||||
{% if dynamicRenderStatus is defined and dynamicRenderStatus == "true" %}
|
|
||||||
<button id="dynamic-render-toggle" title="allow external api" data-enabled="true">
|
|
||||||
<i class="ti ti-arrow-merge"></i>
|
|
||||||
<span id="dynamic-render-status">DYNAMIC PAGE RENDERING</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<button id="dynamic-render-toggle" title="allow external api" data-enabled="false">
|
|
||||||
<i class="ti ti-arrow-merge"></i>
|
|
||||||
<span id="dynamic-render-status">STATIC PAGE RENDERING</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div role="theme">
|
|
||||||
<label>Themes</label><br/>
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div id="dynamic-api">
|
||||||
|
{% if dynamicRenderStatus is defined and dynamicRenderStatus == "true" %}
|
||||||
|
<button id="dynamic-render-toggle" title="allow external api" data-enabled="true">
|
||||||
|
<svg id="dynamic-render-toggle" class="icons">
|
||||||
|
<use id="dynamic-render-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-text-document-inverted"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<span id="dynamic-render-status">DYNAMIC PAGE RENDERING</span>
|
||||||
|
{% else %}
|
||||||
|
<button id="dynamic-render-toggle" title="allow external api" data-enabled="false">
|
||||||
|
<svg id="dynamic-render-toggle" class="icons">
|
||||||
|
<use id="dynamic-render-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-text-document-inverted"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<span id="dynamic-render-status">STATIC PAGE RENDERING</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="option-settings" class="columns">
|
||||||
|
<div id="theme-settings" class="column">
|
||||||
|
<label>THEMES</label>
|
||||||
{% for theme in themes %}
|
{% for theme in themes %}
|
||||||
{% if theme.name == currentTheme %}
|
{% if theme.name == currentTheme %}
|
||||||
<button id="{{ theme.name }}" class="theme-select" data-enabled="true">
|
<a href="#" id="{{theme.name}}" class="theme-select" data-enabled="true">{{theme['display-name']}}</a>
|
||||||
<i class="ti ti-brush"></i>
|
|
||||||
<span>{{ theme['display-name'] }}</span>
|
|
||||||
</button>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<button href="#" id="{{ theme.name }}" class="theme-select" data-enabled="false">
|
<a href="#" id="{{theme.name}}" class="theme-select" data-enabled="false">{{theme['display-name']}}</a>
|
||||||
<i class="ti ti-brush-off"></i>
|
|
||||||
<span>{{ theme['display-name'] }}</span>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div role="mail">
|
<div id="mail-settings" class="column">
|
||||||
<label>Email</label><br/>
|
<label>EMAIL</label>
|
||||||
{% if mailOption == "option-none" or mailOption == "" %}
|
{% if mailOption == "option-none" or mailOption == "" %}
|
||||||
<a href="#" class="mail-option" id="option-none" data-enabled="true">NONE</a>
|
<a href="#" class="mail-option" id="option-none" data-enabled="true">NONE</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -105,19 +135,52 @@
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
{{ include("dash/partials/mailforms.twig") }}
|
{{ include("dash/partials/mailforms.twig") }}
|
||||||
{% endapply %}
|
{% endapply %}
|
||||||
<button id="send-mail">
|
<button id="send-mail">TEST MAIL</button>
|
||||||
<i class="ti ti-mailbox"></i>
|
<br /><br />
|
||||||
<span>TEST MAIL</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</div>
|
||||||
|
<div id="token-settings">
|
||||||
|
<div id="keys-tokens" class="columns">
|
||||||
|
<div class="column">
|
||||||
<label>API KEY</label>
|
<label>API KEY</label>
|
||||||
<br/>
|
<div id="member-api-key">
|
||||||
{{member['key']}}
|
{{member['key']}}
|
||||||
<br/>
|
</div>
|
||||||
<label>FORM TOKEN</label><br/>
|
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<label>FORM TOKEN</label>
|
||||||
|
<div id="form-token">
|
||||||
{{ftoken}}
|
{{ftoken}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
</article>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="backup-settings">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<button id="create-backup">BACK UP YOUR SITE</button><br />
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
{% if lastBackup != '' %}
|
||||||
|
<div class="backup-meta">
|
||||||
|
LAST BACK UP <a href="/api/v1/files">{{lastBackup}}</a><br />
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<span>span No back ups. Frowny face.</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="/assets/scripts/dash.min.js?" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -5,10 +5,12 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=dfdfrtr">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adsfdfdf">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
|
<div id="dash-index">
|
||||||
|
<div id="dash-index-wrapper">
|
||||||
{% if status %}
|
{% if status %}
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
{{ include("dash/partials/index.twig") }}
|
{{ include("dash/partials/index.twig") }}
|
||||||
|
@ -16,4 +18,10 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ include("dash/forms/login.twig") }}
|
{{ include("dash/forms/login.twig") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="/assets/scripts/dash.min.js?" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "are0h/fipamo",
|
"name": "are0h/fipamo",
|
||||||
"descriptions": "The most chill no database blog framework ever.",
|
"descriptions": "The most chill no database blog framework ever.",
|
||||||
"version": "2.6.1-beta",
|
"version": "2.1.1-beta",
|
||||||
"homepage": "https://fipamo.blog",
|
"homepage": "https://fipamo.blog",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@ -10,9 +10,9 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://koodu.ubiqueros.com/are0h/Fipamo",
|
"source": "https://code.playvicio.us/Are0h/Fipamo",
|
||||||
"wiki": "https://koodu.ubiqueros.com/are0h/Fipamo/wiki/?action=_pages",
|
"wiki": "https://code.playvicio.us/Are0h/Fipamo/wiki/_pages",
|
||||||
"issues": "https://koodu.ubiqueros.com/are0h/Fipamo/issues"
|
"issues": "https://code.playvicio.us/Are0h/Fipamo/issues"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"slim/slim": "4.*",
|
"slim/slim": "4.*",
|
||||||
|
@ -22,16 +22,8 @@
|
||||||
"mnapoli/front-yaml": "^1.8",
|
"mnapoli/front-yaml": "^1.8",
|
||||||
"lodash-php/lodash-php": "^0.0.7",
|
"lodash-php/lodash-php": "^0.0.7",
|
||||||
"rbdwllr/reallysimplejwt": "^4.0",
|
"rbdwllr/reallysimplejwt": "^4.0",
|
||||||
|
"fightbulc/moment": "^1.33",
|
||||||
"tgalopin/html-sanitizer": "^1.4",
|
"tgalopin/html-sanitizer": "^1.4",
|
||||||
"phpmailer/phpmailer": "^6.4",
|
"phpmailer/phpmailer": "^6.4"
|
||||||
"league/commonmark": "^2.1",
|
|
||||||
"symfony/yaml": "^5.4",
|
|
||||||
"olegatro/html-sanitizer-relative": "^1.0",
|
|
||||||
"nesbot/carbon": "^2.62"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": [
|
|
||||||
"@php -S localhost:8000 -t public/"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1344
composer.lock
generated
1344
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
{% extends "frame.twig" %}
|
{% extends "fipamo-default/frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
</span>
|
</span>
|
||||||
{% for page in data.pages %}
|
{% for page in data.pages %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug }}">{{page.title}}</a><br />
|
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug }}">{{page.title}}</a><br />
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug~".html" }}">{{page.title}}</a><br />
|
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug~".html" }}">{{page.title}}</a><br />
|
||||||
|
|
|
@ -1,32 +1,31 @@
|
||||||
h1, h2, h3 {
|
/**
|
||||||
color: #ebe5d4;
|
-------------------------------
|
||||||
}
|
-- Typography
|
||||||
|
-------------------------------
|
||||||
h1 {
|
**/
|
||||||
font-size: 2em;
|
/**
|
||||||
font-weight: 400;
|
-------------------------------
|
||||||
}
|
-- Colors
|
||||||
|
-------------------------------
|
||||||
h2 {
|
**/
|
||||||
font-size: 1.75em;
|
/**
|
||||||
font-weight: 400;
|
-------------------------------
|
||||||
}
|
-- Mixins
|
||||||
|
-------------------------------
|
||||||
h3 {
|
**/
|
||||||
font-size: 1.5em;
|
/**
|
||||||
font-weight: 300;
|
-------------------------------
|
||||||
}
|
-- Normalize
|
||||||
|
-------------------------------
|
||||||
|
**/
|
||||||
html {
|
html {
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
-ms-text-size-adjust: 100%;
|
-ms-text-size-adjust: 100%;
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
article,
|
article,
|
||||||
aside,
|
aside,
|
||||||
footer,
|
footer,
|
||||||
|
@ -35,75 +34,62 @@ nav,
|
||||||
section {
|
section {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
margin: 0.67em 0;
|
margin: 0.67em 0;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
figcaption,
|
figcaption,
|
||||||
figure,
|
figure,
|
||||||
main {
|
main {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
margin: 1em 40px;
|
margin: 1em 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
height: 0;
|
height: 0;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
font-family: monospace, monospace;
|
font-family: monospace, monospace;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
-webkit-text-decoration-skip: objects;
|
-webkit-text-decoration-skip: objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:active,
|
a:active,
|
||||||
a:hover {
|
a:hover {
|
||||||
outline-width: 0;
|
outline-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
abbr[title] {
|
abbr[title] {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-decoration: underline dotted;
|
text-decoration: underline dotted;
|
||||||
}
|
}
|
||||||
|
|
||||||
b,
|
b,
|
||||||
strong {
|
strong {
|
||||||
font-weight: inherit;
|
font-weight: inherit;
|
||||||
font-weight: bolder;
|
font-weight: bolder;
|
||||||
}
|
}
|
||||||
|
code,
|
||||||
kbd,
|
kbd,
|
||||||
samp {
|
samp {
|
||||||
font-family: monospace, monospace;
|
font-family: monospace, monospace;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
dfn {
|
dfn {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark {
|
mark {
|
||||||
background-color: #ff0;
|
background-color: #ff0;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub,
|
sub,
|
||||||
sup {
|
sup {
|
||||||
font-size: 60%;
|
font-size: 60%;
|
||||||
|
@ -111,38 +97,31 @@ sup {
|
||||||
position: relative;
|
position: relative;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub {
|
sub {
|
||||||
bottom: -0.25em;
|
bottom: -0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
sup {
|
sup {
|
||||||
top: -0.55em;
|
top: -0.55em;
|
||||||
background: #151d26;
|
background: #bdcbdb;
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0 2px 0 2px;
|
padding: 0 2px 0 2px;
|
||||||
margin: 0 2px 0 0;
|
margin: 0 2px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio,
|
audio,
|
||||||
video {
|
video {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio:not([controls]) {
|
audio:not([controls]) {
|
||||||
display: none;
|
display: none;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg:not(:root) {
|
svg:not(:root) {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
input,
|
input,
|
||||||
optgroup,
|
optgroup,
|
||||||
|
@ -153,44 +132,38 @@ textarea {
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
input {
|
input {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
select {
|
select {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
}
|
}
|
||||||
|
button,
|
||||||
button, html [type=button],
|
html [type="button"],
|
||||||
[type=reset],
|
[type="reset"],
|
||||||
[type=submit] {
|
[type="submit"] {
|
||||||
-webkit-appearance: button;
|
-webkit-appearance: button;
|
||||||
}
|
}
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
[type=button]::-moz-focus-inner,
|
[type="reset"]::-moz-focus-inner,
|
||||||
[type=reset]::-moz-focus-inner,
|
[type="submit"]::-moz-focus-inner,
|
||||||
[type=submit]::-moz-focus-inner,
|
|
||||||
button::-moz-focus-inner {
|
button::-moz-focus-inner {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
[type="button"]:-moz-focusring,
|
||||||
[type=button]:-moz-focusring,
|
[type="reset"]:-moz-focusring,
|
||||||
[type=reset]:-moz-focusring,
|
[type="submit"]:-moz-focusring,
|
||||||
[type=submit]:-moz-focusring,
|
|
||||||
button:-moz-focusring {
|
button:-moz-focusring {
|
||||||
outline: 1px dotted ButtonText;
|
outline: 1px dotted ButtonText;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
border: 1px solid #c0c0c0;
|
border: 1px solid #c0c0c0;
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
padding: 0.35em 0.625em 0.75em;
|
padding: 0.35em 0.625em 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
legend {
|
legend {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
@ -199,140 +172,55 @@ legend {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress {
|
progress {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
[type="checkbox"],
|
||||||
[type=checkbox],
|
[type="radio"] {
|
||||||
[type=radio] {
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
[type=number]::-webkit-inner-spin-button,
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
[type=number]::-webkit-outer-spin-button {
|
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
[type="search"] {
|
||||||
[type=search] {
|
|
||||||
-webkit-appearance: textfield;
|
-webkit-appearance: textfield;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
[type="search"]::-webkit-search-cancel-button,
|
||||||
[type=search]::-webkit-search-cancel-button,
|
[type="search"]::-webkit-search-decoration {
|
||||||
[type=search]::-webkit-search-decoration {
|
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
::-webkit-file-upload-button {
|
||||||
-webkit-appearance: button;
|
-webkit-appearance: button;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
details,
|
details,
|
||||||
menu {
|
menu {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary {
|
summary {
|
||||||
display: list-item;
|
display: list-item;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
template {
|
template {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
[hidden] {
|
[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
form {
|
-------------------------------
|
||||||
display: inline-block;
|
-- Main Structure
|
||||||
}
|
-------------------------------
|
||||||
form a {
|
**/
|
||||||
color: #151d26;
|
|
||||||
}
|
|
||||||
form p {
|
|
||||||
background: #e8c33e;
|
|
||||||
color: #151d26;
|
|
||||||
padding: 5px;
|
|
||||||
display: block;
|
|
||||||
border-radius: 5px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=email], input[type=password], input[type=text] {
|
|
||||||
border: 0;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
margin: 10px 5px 0 0;
|
|
||||||
font: 18px Helvetica, Arial, sans-serif;
|
|
||||||
display: inline-block;
|
|
||||||
background: #151d26;
|
|
||||||
color: #e8c33e;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
border: 0;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #ebe5d4;
|
|
||||||
font: 15px Helvetica, Arial, sans-serif;
|
|
||||||
background: #151d26;
|
|
||||||
}
|
|
||||||
|
|
||||||
button, input[type=submit] {
|
|
||||||
background: #7ED07E;
|
|
||||||
color: #151d26;
|
|
||||||
font: 20px Helvetica, Arial, sans-serif;
|
|
||||||
border-radius: 5px;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 0;
|
|
||||||
padding: 10px 0 5px 0;
|
|
||||||
transition: all 0.3s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
font: 14px Helvetica, Arial, sans-serif;
|
|
||||||
border: 1px solid #FC6399;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
color: #151d26;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-input-placeholder {
|
|
||||||
font: 25px Helvetica, Arial, sans-serif;
|
|
||||||
color: #ebe5d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
:-moz-placeholder {
|
|
||||||
/* Firefox 18- */
|
|
||||||
font: 25px Helvetica, Arial, sans-serif;
|
|
||||||
color: #ebe5d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-moz-placeholder {
|
|
||||||
/* Firefox 19+ */
|
|
||||||
font: 15px Helvetica, Arial, sans-serif;
|
|
||||||
color: #ebe5d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
:-ms-input-placeholder {
|
|
||||||
font: 25px Helvetica, Arial, sans-serif;
|
|
||||||
color: #ebe5d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -341,7 +229,7 @@ html {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font: 400 1.2em/1.4em Helvetica, Arial, sans-serif;
|
font: 400 1.2em/1.4em Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
html body {
|
body {
|
||||||
background: #ebe5d4;
|
background: #ebe5d4;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -352,88 +240,69 @@ html body {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
html body a {
|
a {
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: 1px solid #7ED07E;
|
border-bottom: 1px solid #7ed07e;
|
||||||
|
-moz-transition: all 0.2s linear;
|
||||||
|
-webkit-transition: all 0.2s linear;
|
||||||
|
-o-transition: all 0.2s linear;
|
||||||
|
transition: all 0.2s linear;
|
||||||
}
|
}
|
||||||
html body a:hover {
|
a:hover {
|
||||||
border-bottom: 1px solid #FC6399;
|
border-bottom: 1px solid #fc6399;
|
||||||
}
|
}
|
||||||
html body code {
|
code {
|
||||||
background: #32302f;
|
background: #32302f;
|
||||||
color: #7ED07E;
|
color: #7ed07e;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
html body pre {
|
pre {
|
||||||
background: #32302f;
|
background: #32302f;
|
||||||
color: #7ED07E;
|
color: #7ed07e;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
html body code {
|
pre code {
|
||||||
color: #FC6399;
|
color: #fc6399;
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
html body svg.icons {
|
svg.icons {
|
||||||
width: 25px;
|
width: 25px;
|
||||||
fill: #ebe5d4;
|
fill: #ebe5d4;
|
||||||
}
|
}
|
||||||
html body header {
|
header {
|
||||||
background: #151d26;
|
background: #151d26;
|
||||||
height: 90%;
|
height: 90%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-top: #ebe5d4 3px solid;
|
border-top: #ebe5d4 3px solid;
|
||||||
}
|
}
|
||||||
html body header #media {
|
header nav {
|
||||||
width: 100%;
|
|
||||||
height: 90%;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
html body header #media .slide {
|
|
||||||
transition: all 0.7s linear;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
html body header #media .hide {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
html body header #media .show {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
html body header #media video {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
html body header nav {
|
|
||||||
width: 97%;
|
width: 97%;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
z-index: 1000;
|
|
||||||
position: relative;
|
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
}
|
}
|
||||||
html body header nav .left, html body header nav .right {
|
header nav .left,
|
||||||
|
header nav .right {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
html body header nav .left a.logo-link {
|
header nav .left a.logo-link {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
margin: 0 0 20px 0;
|
margin: 0 0 20px 0;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
html body header nav .left a.logo-link #logo {
|
header nav .left a.logo-link #logo {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
html body header nav .right {
|
header nav .right {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
html body header nav .right a.menu-link {
|
header nav .right a.menu-link {
|
||||||
background: #FC6399;
|
background: #fc6399;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
@ -441,10 +310,10 @@ html body header nav .right a.menu-link {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
html body header nav .right a.menu-link:hover {
|
header nav .right a.menu-link:hover {
|
||||||
background: #FC6399;
|
background: #feb1cc;
|
||||||
}
|
}
|
||||||
html body .container {
|
.container {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
background: #ebe5d4;
|
background: #ebe5d4;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
|
@ -452,7 +321,7 @@ html body .container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: #32302f;
|
color: #32302f;
|
||||||
}
|
}
|
||||||
html body .container article {
|
.container article {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
|
@ -462,139 +331,225 @@ html body .container article {
|
||||||
color: #32302f;
|
color: #32302f;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
html body .container article .index, html body .container article .page {
|
.container article .index,
|
||||||
|
.container article .page {
|
||||||
padding: 0 0 15px 0;
|
padding: 0 0 15px 0;
|
||||||
}
|
}
|
||||||
html body .container article .index img, html body .container article .page img {
|
.container article .index img,
|
||||||
|
.container article .page img {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
html body .container article .index h1, html body .container article .index h2, html body .container article .page h1, html body .container article .page h2 {
|
.container article .index h1,
|
||||||
|
.container article .page h1 {
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
}
|
}
|
||||||
html body .container article .index p, html body .container article .page p {
|
.container article .index p,
|
||||||
|
.container article .page p {
|
||||||
font: 300 1.25em/1.6em Helvetica, Arial, sans-serif;
|
font: 300 1.25em/1.6em Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
html body .container article .index .page_files .page_doc a, html body .container article .page .page_files .page_doc a {
|
.container article .index .meta,
|
||||||
background: #32302f;
|
.container article .page .meta {
|
||||||
border-radius: 3px;
|
|
||||||
color: #ebe5d4;
|
|
||||||
padding: 3px;
|
|
||||||
margin: 0 5px 0 0;
|
|
||||||
}
|
|
||||||
html body .container article .index .meta, html body .container article .page .meta {
|
|
||||||
font: 500 0.8em/1.3em Helvetica, Arial, sans-serif;
|
font: 500 0.8em/1.3em Helvetica, Arial, sans-serif;
|
||||||
padding: 5px 0 0 0;
|
padding: 5px 0 0 0;
|
||||||
border-top: 1px solid #151d26;
|
border-top: 1px solid #151d26;
|
||||||
background: #ebe5d4;
|
background: #ede8d8;
|
||||||
}
|
}
|
||||||
html body .container article .index .meta a, html body .container article .page .meta a {
|
.container article .index .meta a,
|
||||||
|
.container article .page .meta a {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
html body .container article .index .archive-item, html body .container article .page .archive-item {
|
.container article .index .archive-item,
|
||||||
|
.container article .page .archive-item {
|
||||||
padding: 15px 0 20px 0;
|
padding: 15px 0 20px 0;
|
||||||
}
|
}
|
||||||
html body .container article .index .archive-item span.year, html body .container article .page .archive-item span.year {
|
.container article .index .archive-item span.year,
|
||||||
|
.container article .page .archive-item span.year {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
display: block;
|
display: block;
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
}
|
}
|
||||||
html body .container article .index .archive-item .archive-month, html body .container article .page .archive-item .archive-month {
|
.container article .index .archive-item .archive-month,
|
||||||
|
.container article .page .archive-item .archive-month {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
width: 30%;
|
width: 30%;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
html body .container article .index .archive-item .archive-month span.month, html body .container article .page .archive-item .archive-month span.month {
|
.container article .index .archive-item .archive-month span.month,
|
||||||
color: #FC6399;
|
.container article .page .archive-item .archive-month span.month {
|
||||||
|
color: #fc6399;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
html body .container section {
|
.container section {
|
||||||
padding: 0 0 20px 0;
|
padding: 0 0 20px 0;
|
||||||
background: #151d26;
|
background: #151d26;
|
||||||
}
|
}
|
||||||
html body .container section a {
|
.container section a {
|
||||||
color: #ebe5d4;
|
color: #ebe5d4;
|
||||||
}
|
}
|
||||||
html body .container section .index-lists, html body .container section .page-title {
|
.container section .index-lists,
|
||||||
|
.container section .page-title {
|
||||||
max-width: 840px;
|
max-width: 840px;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px 0 0 0;
|
padding: 20px 0 0 0;
|
||||||
}
|
}
|
||||||
html body .container section .index-lists span, html body .container section .page-title span {
|
.container section .index-lists span,
|
||||||
font-size: 2em;
|
.container section .page-title span {
|
||||||
color: #FC6399;
|
font: 600 2em/1.5 Helvetica, Arial, sans-serif;
|
||||||
font-weight: 400;
|
color: #ebe5d4;
|
||||||
width: 80%;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 20px 0 0 0;
|
|
||||||
}
|
}
|
||||||
html body .container section .index-lists .recent, html body .container section .index-lists .featured, html body .container section .page-title .recent, html body .container section .page-title .featured {
|
.container section .index-lists .recent,
|
||||||
|
.container section .page-title .recent,
|
||||||
|
.container section .index-lists .featured,
|
||||||
|
.container section .page-title .featured {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
html body .container section .index-lists label, html body .container section .page-title label {
|
.container section .index-lists label,
|
||||||
|
.container section .page-title label {
|
||||||
background: #32302f;
|
background: #32302f;
|
||||||
color: #ebe5d4;
|
color: #ebe5d4;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
html body footer {
|
footer {
|
||||||
background: #ebe5d4;
|
background: #e4dcc5;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
}
|
}
|
||||||
html body footer .inner {
|
footer .inner {
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
max-width: 840px;
|
max-width: 840px;
|
||||||
}
|
}
|
||||||
html body footer .inner a {
|
footer .inner a {
|
||||||
color: #FC6399;
|
color: #fc6399;
|
||||||
}
|
}
|
||||||
html body header nav {
|
@media only screen and (max-width: 640px) {
|
||||||
|
header nav {
|
||||||
width: 98%;
|
width: 98%;
|
||||||
}
|
}
|
||||||
html body header span {
|
header span {
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
}
|
}
|
||||||
html body header .container article .index .archive-item .archive-month, html body header .container article .page .archive-item .archive-month {
|
.container article .index .archive-item .archive-month,
|
||||||
|
.container article .page .archive-item .archive-month {
|
||||||
width: 45%;
|
width: 45%;
|
||||||
}
|
}
|
||||||
html body header nav {
|
}
|
||||||
|
@media only screen and (max-width: 480px) {
|
||||||
|
header nav {
|
||||||
width: 96%;
|
width: 96%;
|
||||||
}
|
}
|
||||||
html body header .container article .index, html body header .container article .page {
|
.container article .index,
|
||||||
|
.container article .page {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
html body header .container article .index p, html body header .container article .page p {
|
.container article .index p,
|
||||||
|
.container article .page p {
|
||||||
font: 300 1em/1.6em Helvetica, Arial, sans-serif;
|
font: 300 1em/1.6em Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
html body header .container section .index-lists .recent, html body header .container section .index-lists .featured {
|
.container section .index-lists .recent,
|
||||||
|
.container section .index-lists .featured {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
html body header nav {
|
}
|
||||||
|
@media only screen and (max-width: 375px) {
|
||||||
|
header nav {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
}
|
}
|
||||||
html body .container article .index, html body .container article .page {
|
.container article .index,
|
||||||
|
.container article .page {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
html body .container article .index p, html body .container article .page p {
|
.container article .index p,
|
||||||
|
.container article .page p {
|
||||||
font: 300 0.9em/1.7em Helvetica, Arial, sans-serif;
|
font: 300 0.9em/1.7em Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
html body .container article .index .archive-item .archive-month, html body .container article .page .archive-item .archive-month {
|
.container article .index .archive-item .archive-month,
|
||||||
|
.container article .page .archive-item .archive-month {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
-------------------------------
|
||||||
|
-- Forms
|
||||||
|
-------------------------------
|
||||||
|
**/
|
||||||
|
form {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
input[type=email],
|
||||||
|
input[type=password],
|
||||||
|
input[type=text] {
|
||||||
|
border: 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 10px 5px 0 0;
|
||||||
|
font: 15px 'RobotoMono';
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
border: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: $type02;
|
||||||
|
font: 15px 'RobotoMono';
|
||||||
|
}
|
||||||
|
button,
|
||||||
|
input[type=submit] {
|
||||||
|
background: #fc6399;
|
||||||
|
color: #ebe5d4;
|
||||||
|
font: 14px Helvetica, Arial, sans-serif;
|
||||||
|
border-radius: 5px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 0;
|
||||||
|
padding: 5px 5px 0 5px;
|
||||||
|
-moz-transition: all 0.3s linear;
|
||||||
|
-webkit-transition: all 0.3s linear;
|
||||||
|
-o-transition: all 0.3s linear;
|
||||||
|
transition: all 0.3s linear;
|
||||||
|
}
|
||||||
|
button:hover,
|
||||||
|
input[type=submit]:hover {
|
||||||
|
background: #fc7ca9;
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
font: 14px 'RobotoMono';
|
||||||
|
border: 1px solid #fc6399;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
color: #151d26;
|
||||||
|
}
|
||||||
|
::-webkit-input-placeholder {
|
||||||
|
font: 14px 'RobotoMono';
|
||||||
|
color: #837e7c;
|
||||||
|
}
|
||||||
|
:-moz-placeholder {
|
||||||
|
/* Firefox 18- */
|
||||||
|
font: 14px 'RobotoMono';
|
||||||
|
color: #837e7c;
|
||||||
|
}
|
||||||
|
::-moz-placeholder {
|
||||||
|
/* Firefox 19+ */
|
||||||
|
font: 14px 'RobotoMono';
|
||||||
|
color: #837e7c;
|
||||||
|
}
|
||||||
|
:-ms-input-placeholder {
|
||||||
|
font: 14px 'RobotoMono';
|
||||||
|
color: #837e7c;
|
||||||
|
}
|
||||||
/*# sourceMappingURL=base.css.map */
|
/*# sourceMappingURL=base.css.map */
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
@ -1,2 +0,0 @@
|
||||||
(()=>{class e{constructor(){this.currentSlide=0,this.slides=document.querySelectorAll("#media .slide"),this.start()}start(){this.slides.length>1&&(this.slideInterval=setInterval((()=>{this.slides[this.currentSlide].className="slide hide",this.currentSlide=(this.currentSlide+1)%this.slides.length,this.slides[this.currentSlide].className="slide show"}),3e3))}}document.addEventListener("DOMContentLoaded",(function(){new e}),!1)})();
|
|
||||||
//# sourceMappingURL=ThemeStart.js.map
|
|
|
@ -1 +0,0 @@
|
||||||
{"mappings":"4BAKIA,KAAKC,aAAe,EACpBD,KAAKE,OAASC,SAASC,iBAAiB,iBACxCJ,KAAKK,QAEPA,QACML,KAAKE,OAAOI,OAAS,IACvBN,KAAKO,cAAgBC,aAAW,KAC9BR,KAAKE,OAAOF,KAAKC,cAAcQ,UAAY,aAC3CT,KAAKC,cAAgBD,KAAKC,aAAe,GAAKD,KAAKE,OAAOI,OAC1DN,KAAKE,OAAOF,KAAKC,cAAcQ,UAAY,eAC1C,OCbTN,SAASO,iBACP,oBACA,WACa,IAAIC,KAEjB","sources":["src/themes/theme-fipamo-default/com/Base.js","src/themes/theme-fipamo-default/com/ThemeStart.js"],"sourcesContent":["export default class Base {\n //--------------------------\n // constructor\n //--------------------------\n constructor() {\n this.currentSlide = 0;\n this.slides = document.querySelectorAll(\"#media .slide\");\n this.start();\n }\n start() {\n if (this.slides.length > 1) {\n this.slideInterval = setInterval(() => {\n this.slides[this.currentSlide].className = \"slide hide\";\n this.currentSlide = (this.currentSlide + 1) % this.slides.length;\n this.slides[this.currentSlide].className = \"slide show\";\n }, 3000);\n }\n }\n //--------------------------\n // methods\n //--------------------------\n\n //--------------------------\n // event handlers\n //--------------------------\n}\n","import Base from \"./Base.js\";\n\ndocument.addEventListener(\n \"DOMContentLoaded\",\n function () {\n var base = new Base();\n },\n false\n);\n"],"names":["this","currentSlide","slides","document","querySelectorAll","start","length","slideInterval","setInterval","className","addEventListener","$b8d4b81eabebe07b$export$2e2bcd8739ae039"],"version":3,"file":"ThemeStart.js.map"}
|
|
2
content/themes/fipamo-default/assets/scripts/start.min.js
vendored
Normal file
2
content/themes/fipamo-default/assets/scripts/start.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
!function(){"use strict";function n(n,e){for(var t=0;t<e.length;t++){var o=e[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(n,o.key,o)}}var e=function(){function e(){!function(n,e){if(!(n instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.start()}var t,o,r;return t=e,(o=[{key:"start",value:function(){console.log("Connected like F.E.")}}])&&n(t.prototype,o),r&&n(t,r),e}();document.addEventListener("DOMContentLoaded",(function(){new e}),!1)}();
|
||||||
|
//# sourceMappingURL=start.min.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,18 +0,0 @@
|
||||||
{% extends "frame.twig" %}
|
|
||||||
|
|
||||||
{% block title %}
|
|
||||||
{{ title }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block mainContent %}
|
|
||||||
<section>
|
|
||||||
<div class="page-title">
|
|
||||||
<span>{{title}}</span>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<article>
|
|
||||||
<div class="page">
|
|
||||||
<p>{{content | raw}}</p>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
{% endblock %}
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
|
||||||
{% if debug is defined %}
|
{% if debug is defined %}
|
||||||
{% set assetPath = '/src/themes/theme-'~theme~'/'~theme~'/assets/' %}
|
{% set assetPath = '/src/themes/theme-fipamo-default/fipamo-default/assets/' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set assetPath = '/assets/' %}
|
{% set assetPath = '/assets/' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -20,47 +20,10 @@
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
<meta property="og:image" content="{{info["image"]}}" />
|
<meta property="og:image" content="{{info["image"]}}" />
|
||||||
<meta name="twitter:image" content="{{info["image"]}}" />
|
<meta name="twitter:image" content="{{info["image"]}}" />
|
||||||
<link rel="stylesheet" type="text/css" href="{{ assetPath~"css/base.css?=dfvbghh" }}">
|
<link rel="stylesheet" type="text/css" href="{{ assetPath~"css/base.css?=adfafd" }}">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!--
|
|
||||||
<header style="background: url({{ background }}) no-repeat center center; background-size: cover">
|
<header style="background: url({{ background }}) no-repeat center center; background-size: cover">
|
||||||
-->
|
|
||||||
<header>
|
|
||||||
<div id="media">
|
|
||||||
{% if media|length > 1 %}
|
|
||||||
{% for item in media %}
|
|
||||||
{% if item.type == "mp4"%}
|
|
||||||
<div id="{{loop.index0}}" class="slide">
|
|
||||||
<video controls autoplay muted>
|
|
||||||
|
|
||||||
<source src="{{item.file}}" type="video/mp4">
|
|
||||||
|
|
||||||
Please get a better browser. They're free.
|
|
||||||
</video>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div id="{{loop.index0}}" class="slide hide" style="background: url({{ item.file }}) no-repeat center center / cover"></div>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% if media[0] != '' %}
|
|
||||||
{% if media[0].type == "mp4"%}
|
|
||||||
<div id="0" class="slide">
|
|
||||||
<video controls autoplay muted>
|
|
||||||
|
|
||||||
<source src="{{media[0].file}}" type="video/mp4">
|
|
||||||
|
|
||||||
Please get a better browser. They're free.
|
|
||||||
</video>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div id="0" class="slide" style="background: url({{ media[0].file }}) no-repeat center center / cover"></div>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<nav>
|
<nav>
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
<div class="left">
|
<div class="left">
|
||||||
|
@ -72,14 +35,15 @@
|
||||||
{% if menu is defined %}
|
{% if menu is defined %}
|
||||||
{% for link in menu %}
|
{% for link in menu %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="{{"/"~link.slug}}" class="menu-link">{{link.title}}</a><br/>
|
<a href="{{"/"~link.path~"/"~link.slug}}" class="menu-link">{{link.title}}</a><br />
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br/>
|
<a href="{{"/"~link.path~"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br/>
|
<a href="{{"/"~link.path~"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,7 +60,7 @@
|
||||||
<footer>
|
<footer>
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="/archives">Archives</a><br />
|
<a href="/archives">Archives</a><br />
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="/archives.html">Archives</a><br />
|
<a href="/archives.html">Archives</a><br />
|
||||||
|
@ -104,9 +68,10 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="/archives.html">Archives</a><br />
|
<a href="/archives.html">Archives</a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
© 2020 By Fipamo
|
© 2020 By Fipamo
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<script src="{{ assetPath~"scripts/ThemeStart.js" }}" type="text/javascript"></script>
|
<script src="{{ assetPath~"scripts/start.min.js" }}" type="text/javascript"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "frame.twig" %}
|
{% extends "fipamo-default/frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
<span>RECENT</span><br />
|
<span>RECENT</span><br />
|
||||||
{% for item in recent %}
|
{% for item in recent %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="{{ "/"~item.path~"/"~item.slug}}"> {{item.title}} </a><br />
|
<a href="{{ "/"~item.path~"/"~item.slug}}"> {{item.title}} </a><br />
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
||||||
|
@ -34,12 +34,11 @@
|
||||||
<span>FEATURED</span><br />
|
<span>FEATURED</span><br />
|
||||||
{% for item in featured %}
|
{% for item in featured %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="{{ "/"~item.path~"/"~item.slug}}"> {{item.title}} </a><br />
|
<a href="{{ "/"~item.path~"/"~item.slug}}"> {{item.title}} </a><br />
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "frame.twig" %}
|
{% extends "fipamo-default/frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -7,44 +7,20 @@
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
<section>
|
<section>
|
||||||
<div class="page-title">
|
<div class="page-title">
|
||||||
<span>{{title}}</span><br>
|
<span>{{title}}</span>
|
||||||
This is a custom temlate
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<article>
|
<article>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
|
THIS IS A CUSTOM TEMPLATE <br />
|
||||||
<p>{{content | raw}}</p>
|
<p>{{content | raw}}</p>
|
||||||
<div>
|
<div>
|
||||||
<div class="page_files">
|
|
||||||
<div class="page_doc">
|
|
||||||
<strong>Files</strong><br/>
|
|
||||||
{% for doc in files %}
|
|
||||||
{% if doc.type != "mp3" %}
|
|
||||||
{% set path = doc.file|split('/') %}
|
|
||||||
<a href="{{doc.file}}">{{path[6]}}</a>
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
<div class="page_sounds">
|
|
||||||
<strong>Sounds</strong><br/>
|
|
||||||
{% for doc in files %}
|
|
||||||
{% if doc.type == "mp3" %}
|
|
||||||
<audio controls>
|
|
||||||
<source src="{{doc.file}}" type="audio/mpeg">
|
|
||||||
Your browser does not support the audio element.
|
|
||||||
</audio>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
{{meta['who']}} dropped this {{ meta['when'] }}<br />
|
{{meta['who']}} dropped this {{ meta['when'] }}<br />
|
||||||
<strong>tags: </strong>
|
<strong>tags: </strong>
|
||||||
{% for tag in meta['tags'] %}
|
{% for tag in meta['tags'] %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
|
@ -52,8 +28,8 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "frame.twig" %}
|
{% extends "fipamo-default/frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -14,39 +14,12 @@
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<p>{{content | raw}}</p>
|
<p>{{content | raw}}</p>
|
||||||
<div>
|
<div>
|
||||||
<div class="page_files">
|
|
||||||
<div class="page_doc">
|
|
||||||
<strong>Files</strong><br/>
|
|
||||||
{% for doc in files %}
|
|
||||||
{% if doc.type != "mp3" %}
|
|
||||||
{% set path = doc.file|split('/') %}
|
|
||||||
<a href="{{doc.file}}">{{path[6]}}</a>
|
|
||||||
|
|
||||||
{% endif %}
|
{{meta['who']}} dropped this {{ meta['when'] }}<br />
|
||||||
{% endfor %}
|
<strong>tags: </strong>
|
||||||
</div>
|
|
||||||
<div class="page_sounds">
|
|
||||||
<strong>Sounds</strong><br/>
|
|
||||||
{% for doc in files %}
|
|
||||||
{% if doc.type == "mp3" %}
|
|
||||||
<audio controls>
|
|
||||||
<source src="{{doc.file}}" type="audio/mpeg">
|
|
||||||
Your browser does not support the audio element.
|
|
||||||
</audio>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
{{meta['who']}}
|
|
||||||
dropped this
|
|
||||||
{{ meta['when'] }}<br/>
|
|
||||||
<strong>tags:
|
|
||||||
</strong>
|
|
||||||
{% for tag in meta['tags'] %}
|
{% for tag in meta['tags'] %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
|
@ -54,8 +27,8 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "frame.twig" %}
|
{% extends "fipamo-default/frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
<div class="page">
|
<div class="page">
|
||||||
{% for tag in tag_list %}
|
{% for tag in tag_list %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender %}
|
||||||
<a href="{{"/"~tag.path~"/"~tag.slug}}">{{tag.title}}</a><br />
|
<a href="{{"/"~tag.path~"/"~tag.slug}}">{{tag.title}}</a><br />
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
|
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
|
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
8025
package-lock.json
generated
8025
package-lock.json
generated
File diff suppressed because it is too large
Load diff
34
package.json
34
package.json
|
@ -1,34 +0,0 @@
|
||||||
{
|
|
||||||
"name": "fipamo-dash",
|
|
||||||
"version": "2.6.1-beta",
|
|
||||||
"private": true,
|
|
||||||
"apidoc": {
|
|
||||||
"name": "Fipamo API",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "The most chill API for the most chill blog framework"
|
|
||||||
},
|
|
||||||
"source": "src/com/Start.js",
|
|
||||||
"main": "public/assets/scripts/dash.js",
|
|
||||||
"targets": {
|
|
||||||
"main": {
|
|
||||||
"includeNodeModules": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"watch": "parcel watch",
|
|
||||||
"build": "parcel build"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/core": "^7.21.3",
|
|
||||||
"babel-plugin-prismjs": "^2.1.0",
|
|
||||||
"parcel": "^2.8.3",
|
|
||||||
"prettier": "^2.8.4",
|
|
||||||
"stylelint": "^15.3.0",
|
|
||||||
"stylelint-config-standard": "^31.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"animejs": "^3.2.1",
|
|
||||||
"prismjs": "^1.29.0",
|
|
||||||
"sortablejs": "^1.15.0"
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue