2.5.0 commit part 1, whew
This commit is contained in:
commit
7cefc12692
90 changed files with 5063 additions and 3883 deletions
136
.eslintrc
136
.eslintrc
|
@ -1,70 +1,70 @@
|
|||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 7,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {}
|
||||
},
|
||||
"rules": {
|
||||
"constructor-super": 2,
|
||||
"for-direction": 2,
|
||||
"getter-return": 2,
|
||||
"no-case-declarations": 2,
|
||||
"no-class-assign": 2,
|
||||
"no-compare-neg-zero": 2,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 1,
|
||||
"no-const-assign": 2,
|
||||
"no-constant-condition": 2,
|
||||
"no-control-regex": 1,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-class-members": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-empty": 2,
|
||||
"no-empty-character-class": 2,
|
||||
"no-empty-pattern": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-semi": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-global-assign": 2,
|
||||
"no-inner-declarations": 2,
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-new-symbol": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-redeclare": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-self-assign": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-this-before-super": 2,
|
||||
"no-undef": 2,
|
||||
"no-unexpected-multiline": 2,
|
||||
"no-unreachable": 2,
|
||||
"no-unsafe-finally": 2,
|
||||
"no-unsafe-negation": 2,
|
||||
"no-unused-labels": 2,
|
||||
"no-unused-vars": 2,
|
||||
"no-useless-escape": 1,
|
||||
"require-yield": 2,
|
||||
"use-isnan": 2,
|
||||
"valid-typeof": 2,
|
||||
"no-duplicate-imports": 2
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"_": false,
|
||||
"hljs": false,
|
||||
"Sortable": false,
|
||||
"Prism": false
|
||||
}
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 7,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {}
|
||||
},
|
||||
"rules": {
|
||||
"constructor-super": 2,
|
||||
"for-direction": 2,
|
||||
"getter-return": 2,
|
||||
"no-case-declarations": 2,
|
||||
"no-class-assign": 2,
|
||||
"no-compare-neg-zero": 2,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 1,
|
||||
"no-const-assign": 2,
|
||||
"no-constant-condition": 2,
|
||||
"no-control-regex": 1,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-class-members": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-empty": 2,
|
||||
"no-empty-character-class": 2,
|
||||
"no-empty-pattern": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-semi": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-global-assign": 2,
|
||||
"no-inner-declarations": 2,
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-new-symbol": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-redeclare": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-self-assign": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-this-before-super": 2,
|
||||
"no-undef": 2,
|
||||
"no-unexpected-multiline": 2,
|
||||
"no-unreachable": 2,
|
||||
"no-unsafe-finally": 2,
|
||||
"no-unsafe-negation": 2,
|
||||
"no-unused-labels": 2,
|
||||
"no-unused-vars": 1,
|
||||
"no-useless-escape": 1,
|
||||
"require-yield": 2,
|
||||
"use-isnan": 2,
|
||||
"valid-typeof": 2,
|
||||
"no-duplicate-imports": 2
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"_": false,
|
||||
"hljs": false,
|
||||
"Sortable": false,
|
||||
"Prism": false
|
||||
}
|
||||
}
|
7
.prettierignore
Normal file
7
.prettierignore
Normal file
|
@ -0,0 +1,7 @@
|
|||
.babelrc
|
||||
README.md
|
||||
*.twig
|
||||
*.sass
|
||||
*.json
|
||||
*.php
|
||||
*.md
|
17
.prettierrc
Normal file
17
.prettierrc
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"arrowParens": "avoid",
|
||||
"bracketSpacing": true,
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"insertPragma": false,
|
||||
"bracketSameLine": false,
|
||||
"jsxSingleQuote": true,
|
||||
"parser": "babel",
|
||||
"proseWrap": "preserve",
|
||||
"requirePragma": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"useTabs": true,
|
||||
"tabWidth": 4,
|
||||
"printWidth": 90
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
<?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/data/Contents.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,74 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
79
brain/api/v1/AuthAPI.php
Normal file
79
brain/api/v1/AuthAPI.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?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,76 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
81
brain/api/v1/ImagesAPI.php
Normal file
81
brain/api/v1/ImagesAPI.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace brain\api\v1;
|
||||
|
||||
use brain\data\Member;
|
||||
use brain\data\Settings;
|
||||
|
||||
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,30 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
34
brain/api/v1/InitAPI.php
Normal file
34
brain/api/v1/InitAPI.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
31
brain/api/v1/MailerAPI.php
Normal file
31
brain/api/v1/MailerAPI.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?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
|
||||
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,171 +0,0 @@
|
|||
<?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())->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;
|
||||
}
|
||||
}
|
180
brain/api/v1/PagesAPI.php
Normal file
180
brain/api/v1/PagesAPI.php
Normal file
|
@ -0,0 +1,180 @@
|
|||
<?php
|
||||
|
||||
namespace brain\api\v1;
|
||||
|
||||
use Mni\FrontYAML\Parser;
|
||||
use brain\api\v1\ImagesAPI;
|
||||
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 = $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())->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,147 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
154
brain/api/v1/SettingsAPI.php
Normal file
154
brain/api/v1/SettingsAPI.php
Normal file
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
namespace brain\api\v1;
|
||||
|
||||
use Slim\Views\Twig;
|
||||
use brain\api\v1\ImagesApi;
|
||||
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"])) {
|
||||
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,227 +0,0 @@
|
|||
<?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");
|
||||
}
|
||||
}
|
232
brain/controller/APIControl.php
Normal file
232
brain/controller/APIControl.php
Normal file
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
|
||||
namespace brain\controller;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use brain\api\v1\AuthAPI;
|
||||
use brain\api\v1\ImagesAPI;
|
||||
use brain\api\v1\PagesAPI;
|
||||
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 "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,189 +0,0 @@
|
|||
<?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())->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":
|
||||
$page = (new Book())->findPageById($uuid);
|
||||
$views = [];
|
||||
if (str_contains($page["layout"], "index")) {
|
||||
$views = (new Themes())->getCustomIndex();
|
||||
} else {
|
||||
$views = (new Themes())->getCustomViews();
|
||||
}
|
||||
$pageOptions = [
|
||||
"title" => "Fipamo | Edit Page",
|
||||
"page" => $page,
|
||||
"mode" => $mode,
|
||||
"token" => Session::get("form_token"),
|
||||
"status" => Session::active(),
|
||||
"views" => $views,
|
||||
];
|
||||
break;
|
||||
case "preview":
|
||||
$config = new Settings();
|
||||
$settings = $config->getSettings();
|
||||
$loader = new \Twig\Loader\FilesystemLoader(
|
||||
"../content/themes"
|
||||
);
|
||||
$display = new \Twig\Environment($loader, []);
|
||||
|
||||
$book = new Book();
|
||||
$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())->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);
|
||||
}
|
||||
}
|
218
brain/controller/DashControl.php
Normal file
218
brain/controller/DashControl.php
Normal file
|
@ -0,0 +1,218 @@
|
|||
<?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 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 \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');
|
||||
exit();
|
||||
}
|
||||
|
||||
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');
|
||||
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 (str_contains($page['layout'], 'index')) {
|
||||
$views = (new Themes())->getCustomIndex();
|
||||
} else {
|
||||
$views = (new Themes())->getCustomViews();
|
||||
}
|
||||
|
||||
$imageList = explode(',', $page['feature']);
|
||||
$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' => 'Fipamo | Edit Page',
|
||||
'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'
|
||||
);
|
||||
$display = new \Twig\Environment($loader, []);
|
||||
|
||||
$book = new Book();
|
||||
$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');
|
||||
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' => 'Welcome Back',
|
||||
'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);
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
<?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 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;
|
||||
}
|
||||
}
|
||||
}
|
113
brain/controller/IndexControl.php
Normal file
113
brain/controller/IndexControl.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
}
|
48
brain/controller/RouteControl.php
Normal file
48
brain/controller/RouteControl.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace brain\controller;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use brain\controller\DashControl;
|
||||
use brain\controller\APIControl;
|
||||
use brain\controller\IndexControl;
|
||||
|
||||
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":
|
||||
//$result = APIControl::post($request, $response, $args);
|
||||
//var_dump($result);
|
||||
return APIControl::post($request, $response, $args);
|
||||
break;
|
||||
default:
|
||||
//echo "YES";
|
||||
//return IndexControl::start($request, $response, $args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
<?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();
|
||||
}
|
||||
}
|
159
brain/data/Auth.php
Normal file
159
brain/data/Auth.php
Normal file
|
@ -0,0 +1,159 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use ReallySimpleJWT\Token;
|
||||
use brain\data\Settings;
|
||||
use brain\data\Session;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,265 +0,0 @@
|
|||
<?php
|
||||
|
||||
use function _\filter;
|
||||
use function _\find;
|
||||
|
||||
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();
|
||||
if ($task == "delete") {
|
||||
//$parsed = json_decode(file_get_contents("php://input"), true);
|
||||
//$body = find($content, ["uuid" => $parsed["id"]]);
|
||||
$body = $request->getParsedBody();
|
||||
} 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"] = "false";
|
||||
$body["published"] = "false";
|
||||
$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;
|
||||
$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;
|
||||
}
|
||||
}
|
298
brain/data/Book.php
Normal file
298
brain/data/Book.php
Normal file
|
@ -0,0 +1,298 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use function _\filter;
|
||||
use function _\find;
|
||||
use brain\utility\DocTools;
|
||||
use brain\utility\FileUploader;
|
||||
use brain\utility\StringTools;
|
||||
|
||||
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();
|
||||
if ($task == 'delete') {
|
||||
// $parsed = json_decode(file_get_contents("php://input"), true);
|
||||
// $body = find($content, ["uuid" => $parsed["id"]]);
|
||||
$body = $request->getParsedBody();
|
||||
} else {
|
||||
$body = $request->getParsedBody();
|
||||
}
|
||||
|
||||
$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 (isset($files['page_files'])) {
|
||||
$imageList = '';
|
||||
$fileList = '';
|
||||
// var_dump($files["page_files"] );
|
||||
foreach ($files['page_files'] as $file) {
|
||||
$type = $file->getClientMediaType();
|
||||
switch ($type) {
|
||||
case 'image/jpeg':
|
||||
case 'image/png':
|
||||
case 'image/gif':
|
||||
case 'image/svg':
|
||||
$imagesPath = '/assets/images/blog/'.$path.'/';
|
||||
$imageList =
|
||||
$imageList.$imagesPath.urlencode($file->getClientFileName()).', ';
|
||||
|
||||
FileUploader::uploadFile(
|
||||
'../public/assets/images/blog/'.$path.'/',
|
||||
$file
|
||||
);
|
||||
break;
|
||||
case 'video/mp4':
|
||||
$videosPath = '/assets/video/blog/'.$path.'/';
|
||||
$imageList =
|
||||
$imageList.$videosPath.urlencode($file->getClientFileName()).', ';
|
||||
|
||||
FileUploader::uploadFile(
|
||||
'../public/assets/video/blog/'.$path.'/',
|
||||
$file
|
||||
);
|
||||
break;
|
||||
case 'audio/mpeg':
|
||||
$soundPath = '/assets/sound/blog/'.$path.'/';
|
||||
$fileList = $fileList.$soundPath.urlencode($file->getClientFileName()).', ';
|
||||
|
||||
FileUploader::uploadFile(
|
||||
'../public/assets/sound/blog/'.$path.'/',
|
||||
$file
|
||||
);
|
||||
break;
|
||||
case 'application/pdf':
|
||||
case 'text/plain':
|
||||
case 'text/rtf':
|
||||
$docPath = '/assets/docs/blog/'.$path.'/';
|
||||
$fileList = $fileList.$docPath.urlencode($file->getClientFileName()).', ';
|
||||
|
||||
FileUploader::uploadFile(
|
||||
'../public/assets/docs/blog/'.$path.'/',
|
||||
$file
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$page_feature = $imageList;
|
||||
$page_files = $fileList;
|
||||
} else {
|
||||
// if no files, just reset string from page object
|
||||
$page_feature = $page['feature'];
|
||||
$page_files = $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 \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'] = $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,144 +0,0 @@
|
|||
<?php
|
||||
use League\CommonMark\Environment\Environment;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
|
||||
use League\CommonMark\Extension\Attributes\AttributesExtension;
|
||||
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
|
||||
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
|
||||
use League\CommonMark\MarkdownConverter;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
use HtmlSanitizer\Extension\Basic\BasicExtension;
|
||||
use HtmlSanitizer\Extension\Iframe\IframeExtension;
|
||||
use HtmlSanitizer\SanitizerBuilder;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// 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
|
||||
|
||||
$builder = new SanitizerBuilder();
|
||||
$builder->registerExtension(new BasicExtension());
|
||||
$builder->registerExtension(new IframeExtension());
|
||||
|
||||
//relative-a and relative-image
|
||||
$builder->registerExtension(
|
||||
new \HtmlSanitizer\Extension\Relative\A\AExtension()
|
||||
);
|
||||
$builder->registerExtension(
|
||||
new \HtmlSanitizer\Extension\Relative\Image\ImageExtension()
|
||||
);
|
||||
|
||||
$detergent = [
|
||||
"extensions" => ["basic", "relative-a", "relative-image", "iframe"],
|
||||
"tags" => [
|
||||
"div" => [
|
||||
"allowed_attributes" => ["class", "title"],
|
||||
],
|
||||
"img" => [
|
||||
"allowed_attributes" => ["src", "alt", "title", "class"],
|
||||
],
|
||||
"iframe" => [
|
||||
"allowed_attributes" => ["height", "width", "title", "src"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$sanitizer = $builder->build($detergent);
|
||||
|
||||
$scrubbed = $sanitizer->sanitize($result->getContent());
|
||||
|
||||
//sort attributes into page object
|
||||
$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" => $parsed->getContent(),
|
||||
"html" => $scrubbed,
|
||||
];
|
||||
//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;
|
||||
}
|
||||
}
|
178
brain/data/Contents.php
Normal file
178
brain/data/Contents.php
Normal file
|
@ -0,0 +1,178 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use League\CommonMark\Environment\Environment;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
|
||||
use League\CommonMark\Extension\Attributes\AttributesExtension;
|
||||
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
|
||||
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
|
||||
use League\CommonMark\MarkdownConverter;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use HtmlSanitizer\Extension\Basic\BasicExtension;
|
||||
use HtmlSanitizer\Extension\Iframe\IframeExtension;
|
||||
use HtmlSanitizer\Extension\Listing\ListExtension;
|
||||
use HtmlSanitizer\SanitizerBuilder;
|
||||
|
||||
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());
|
||||
|
||||
// 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());
|
||||
|
||||
//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"],
|
||||
"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());
|
||||
$featureList = explode(",", $meta["feature"]);
|
||||
$docs = '';
|
||||
if (isset($meta["files"])) {
|
||||
$fileList = explode(",", $meta["files"]);
|
||||
$docs = $meta["files"];
|
||||
} else {
|
||||
$fileList = [];
|
||||
$docs = '';
|
||||
}
|
||||
|
||||
$media = [];
|
||||
$files = [];
|
||||
foreach ($featureList as $file) {
|
||||
$item = trim($file);
|
||||
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
||||
if ($item != null || $item != "") {
|
||||
array_push($media, ["file" => $item, "type" => trim($ext)]);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
||||
}
|
62
brain/data/Member.php
Normal file
62
brain/data/Member.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use brain\data\Settings;
|
||||
use brain\data\Session;
|
||||
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 = 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,179 +0,0 @@
|
|||
<?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())->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 = $this->theme . "/" . $layout . ".twig";
|
||||
if (str_contains($page["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 = $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()
|
||||
{
|
||||
//TODO: Need to fix this to account for new index templating system
|
||||
$pages = (new Book())->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);
|
||||
}
|
||||
}
|
206
brain/data/Render.php
Normal file
206
brain/data/Render.php
Normal file
|
@ -0,0 +1,206 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use Mni\FrontYAML\Parser;
|
||||
use brain\data\Settings;
|
||||
use brain\data\Book;
|
||||
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($page["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,
|
||||
];
|
||||
|
||||
$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,
|
||||
];
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
94
brain/data/Session.php
Normal file
94
brain/data/Session.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use ReallySimpleJWT\Token;
|
||||
|
||||
use function _\find;
|
||||
|
||||
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,169 +0,0 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
177
brain/data/Settings.php
Normal file
177
brain/data/Settings.php
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use brain\data\Member;
|
||||
use brain\utility\DocTools;
|
||||
use brain\utility\Sorting;
|
||||
|
||||
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,60 +0,0 @@
|
|||
<?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 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;
|
||||
}
|
||||
}
|
64
brain/data/Themes.php
Normal file
64
brain/data/Themes.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace brain\data;
|
||||
|
||||
use brain\data\Settings;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
36
brain/init/App.php
Normal file
36
brain/init/App.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace brain\init;
|
||||
|
||||
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;
|
||||
// Fipamo Core Classes
|
||||
use brain\utility\HandleCors;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
145
brain/utility/DocTools.php
Normal file
145
brain/utility/DocTools.php
Normal file
|
@ -0,0 +1,145 @@
|
|||
<?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["feature"] .
|
||||
"\n" .
|
||||
"files: " .
|
||||
$object["files"] .
|
||||
"\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,32 +0,0 @@
|
|||
<?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");
|
||||
}
|
||||
}
|
||||
}
|
32
brain/utility/FileUploader.php
Normal file
32
brain/utility/FileUploader.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?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,6 +1,10 @@
|
|||
<?php
|
||||
|
||||
class handleCors
|
||||
namespace brain\utility;
|
||||
|
||||
use brain\data\Settings;
|
||||
|
||||
class HandleCors
|
||||
{
|
||||
public function __construct()
|
||||
{
|
|
@ -1,94 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
98
brain/utility/Mailer.php
Normal file
98
brain/utility/Mailer.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace brain\utility;
|
||||
|
||||
use Slim\Views\Twig;
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
104
brain/utility/Maintenance.php
Normal file
104
brain/utility/Maintenance.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace brain\utility;
|
||||
|
||||
use brain\data\Settings;
|
||||
|
||||
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,223 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
229
brain/utility/Setup.php
Normal file
229
brain/utility/Setup.php
Normal file
|
@ -0,0 +1,229 @@
|
|||
<?php
|
||||
|
||||
namespace brain\utility;
|
||||
|
||||
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",
|
||||
"files" => "",
|
||||
"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;
|
||||
}
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
<?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"],
|
||||
"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::$_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())->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"],
|
||||
];
|
||||
} 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"],
|
||||
];
|
||||
}
|
||||
return $pageOptions;
|
||||
}
|
||||
}
|
248
brain/utility/Sorting.php
Normal file
248
brain/utility/Sorting.php
Normal file
|
@ -0,0 +1,248 @@
|
|||
<?php
|
||||
|
||||
namespace brain\utility;
|
||||
|
||||
use Mni\FrontYAML\Parser;
|
||||
use brain\data\Book;
|
||||
use brain\data\Settings;
|
||||
|
||||
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"],
|
||||
"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::$_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())->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;
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
132
brain/utility/StringTools.php
Normal file
132
brain/utility/StringTools.php
Normal file
|
@ -0,0 +1,132 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfdfa">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfvgy">
|
||||
{% endblock %}
|
||||
|
||||
{% block mainContent %}
|
||||
|
@ -45,58 +45,36 @@
|
|||
</div>
|
||||
<div id="posts-list">
|
||||
{% for page in pages %}
|
||||
<a class="page-link" href="/dashboard/page/edit/{{ page.uuid }}">
|
||||
<div class="page-bg" style="background: url({{ page.feature }}) no-repeat center center / cover">
|
||||
<label>
|
||||
{{ page.title }}
|
||||
</label>
|
||||
<div id="meta">
|
||||
{% 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">
|
||||
|
||||
<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>
|
||||
Sorry, your browser doesn't support embedded videos.
|
||||
</video>
|
||||
<label>
|
||||
{{ page.title }}
|
||||
</label>
|
||||
<div id="meta">
|
||||
{{ include("dash/partials/recent-options.twig") }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</a>
|
||||
{% else %}
|
||||
<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">
|
||||
<label>
|
||||
{{ page.title }}
|
||||
</label>
|
||||
<div id="meta">
|
||||
{{ include("dash/partials/recent-options.twig") }}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
{% if numOfPages > 1 %}
|
||||
<div class="paginate">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div id="dash-login">
|
||||
<div id="dash-form" class="dash-form">
|
||||
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
||||
<form id="login" class='login' name="login" action="/dashboard/login" method="POST">
|
||||
<form id="login" class='login' name="login" method="POST">
|
||||
<input type="text" name="handle" class="form-control" placeholder="Handle" required ">
|
||||
<input type="password" name="password" class="form-control" placeholder="Password" required">
|
||||
<button id="login-btn" class='login-btn' type='submit'>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<div id="dash-index">
|
||||
<div id="dash-index-wrapper">
|
||||
<div id="dash-init" class="dash-init">
|
||||
<form id="init-form">
|
||||
<form id="init-form" method="POST">
|
||||
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
|
||||
<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"/>
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
</div>
|
||||
<div id="dash-restore" class="dash-restore">
|
||||
<form id="init-restore">
|
||||
<form id="init-restore" method="POST">
|
||||
<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>
|
||||
|
@ -44,5 +44,5 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="/assets/scripts/Start.js" type="text/javascript"></script>
|
||||
<script src="/assets/scripts/Start.js?=sdfsdf" type="text/javascript"></script>
|
||||
{% endblock %}
|
|
@ -39,5 +39,5 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="/assets/scripts/Start.js" type="text/javascript"></script>
|
||||
<script src="/assets/scripts/Start.js?=cvfggt" type="text/javascript"></script>
|
||||
{% endblock %}
|
|
@ -14,6 +14,8 @@
|
|||
{% set content = page['content'] %}
|
||||
{% set date = page['created'] %}
|
||||
{% set updated = page['updated'] %}
|
||||
{% set media = page['media'] %}
|
||||
{% set files = page['docs'] %}
|
||||
{% else %}
|
||||
{% set id = '' %}
|
||||
{% set uuid = '' %}
|
||||
|
@ -25,6 +27,8 @@
|
|||
{% set content = '' %}
|
||||
{% set date = '' %}
|
||||
{% set updated = '' %}
|
||||
{% set media = '' %}
|
||||
{% set files = '' %}
|
||||
{% endif %}
|
||||
|
||||
{% block title %}
|
||||
|
@ -32,7 +36,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=qwert">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=vbhj">
|
||||
{% endblock %}
|
||||
|
||||
{% block mainContent %}
|
||||
|
@ -40,19 +44,73 @@
|
|||
<div id="post-edit-index-wrapper">
|
||||
<div id="post-feature">
|
||||
{% if page['feature'] == null %}
|
||||
<div id="featured-image-drop">
|
||||
DRAG AND DROP IMAGE OR <label for="featured-image-upload">CLICK TO CHOSE</label>
|
||||
<div id="page-file-manager">
|
||||
<div id="page-file-wrapper">
|
||||
<div id="page-file-drop">
|
||||
<label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label>
|
||||
</div>
|
||||
IMAGES AND VIDEO
|
||||
<div id="page-images-list"></div>
|
||||
FILES
|
||||
<div id="page-files-list"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% else %}
|
||||
<div id="featured-new-image-btn">
|
||||
<button id="new-feature-upload">
|
||||
<svg id="new-feature-upload" viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-image-inverted"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="featured-image-drop">
|
||||
<img id="featured-image" src="{{ feature }}"/>
|
||||
</div>
|
||||
<div id="page-file-manager">
|
||||
<div id="page-file-wrapper">
|
||||
<div id="page-file-drop">
|
||||
<label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label>
|
||||
</div>
|
||||
IMAGES AND VIDEO
|
||||
<div id="page-images-list">
|
||||
{% if media|length > 1 %}
|
||||
{% for item in media %}
|
||||
{% if item.type == "mp4"%}
|
||||
<div id="{{loop.index0}}" class="video-item" data-source="{{ item.file }}"></div>
|
||||
{% else %}
|
||||
<div id="{{loop.index0}}" class="img-item" 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="video-item" data-source="{{ media[0].file }}"></div>
|
||||
{% else %}
|
||||
<div id="0" class="img-item" style="background: url({{ media[0].file }}) no-repeat center center / cover"></div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
FILES
|
||||
<div id="page-files-list">
|
||||
{% if files|length > 1 %}
|
||||
{% for item in files %}
|
||||
{% if item.type == "mp3"%}
|
||||
<div id="{{loop.index0}}" class="audio-item" data-source="{{ item.file }}"></div>
|
||||
{% else %}
|
||||
<div id="{{loop.index0}}" class="file-item" data-source="{{ item.file }}"></div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% if files[0] != '' %}
|
||||
{% if files[0].type == "mp3"%}
|
||||
<div id="0" class="audio-item" data-source="{{ files[0].file }}"></div>
|
||||
{% else %}
|
||||
<div id="0" class="file-item" data-source="{{ files[0].file }}"></div>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
@ -95,7 +153,7 @@
|
|||
<span id="post-date" type="text">
|
||||
{{ updated }}
|
||||
</span>
|
||||
<input id="featured-image-upload" type="file" name="featured-image-upload"/>
|
||||
<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="form_token" name="token" type="hidden" value="{{ token }}">
|
||||
</div>
|
||||
|
@ -119,5 +177,5 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="/assets/scripts/Start.js" type="text/javascript"></script>
|
||||
<script src="/assets/scripts/Start.js?=erty" type="text/javascript"></script>
|
||||
{% endblock %}
|
|
@ -25,53 +25,30 @@
|
|||
<br/>
|
||||
{% if data["entryCount"] != 0 %}
|
||||
{% for page in data['pages'] %}
|
||||
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-link" style="background: url({{ page.feature }}) no-repeat center center / cover">
|
||||
<label>
|
||||
{{ page.title }}
|
||||
</label>
|
||||
<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">
|
||||
{% if page.media[0].type == 'mp4' %}
|
||||
|
||||
<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>
|
||||
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-video-link">
|
||||
<video class="post-video" loop muted autoplay>
|
||||
<source src="{{ page.media[0].file }}" type="video/mp4">
|
||||
|
||||
<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>
|
||||
Sorry, your browser doesn't support embedded videos.
|
||||
</video>
|
||||
<label>
|
||||
{{ page.title }}
|
||||
</label>
|
||||
{{ include("dash/partials/recent-options.twig") }}
|
||||
</a>
|
||||
|
||||
{% else %}
|
||||
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-link" style="background: url({{ page.media[0].file }}) no-repeat center center / cover">
|
||||
<label>
|
||||
{{ page.title }}
|
||||
</label>
|
||||
|
||||
{{ include("dash/partials/recent-options.twig") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
There are no pages
|
||||
|
|
42
brain/views/dash/partials/recent-options.twig
Normal file
42
brain/views/dash/partials/recent-options.twig
Normal file
|
@ -0,0 +1,42 @@
|
|||
<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>
|
|
@ -5,7 +5,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfd">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfdff">
|
||||
{% endblock %}
|
||||
|
||||
{% block mainContent %}
|
||||
|
@ -23,5 +23,5 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="/assets/scripts/Start.js" type="text/javascript"></script>
|
||||
<script src="/assets/scripts/Start.js?=ghji" type="text/javascript"></script>
|
||||
{% endblock %}
|
|
@ -9,6 +9,11 @@
|
|||
"homepage": "https://roiskinda.cool"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"brain\\":"brain"
|
||||
}
|
||||
},
|
||||
"support": {
|
||||
"source": "https://code.playvicio.us/Are0h/Fipamo",
|
||||
"wiki": "https://code.playvicio.us/Are0h/Fipamo/wiki/_pages",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "fipamo-default/frame.twig" %}
|
||||
{% extends "frame.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{{ title }}
|
||||
|
|
|
@ -1,31 +1,32 @@
|
|||
/**
|
||||
-------------------------------
|
||||
-- Typography
|
||||
-------------------------------
|
||||
**/
|
||||
/**
|
||||
-------------------------------
|
||||
-- Colors
|
||||
-------------------------------
|
||||
**/
|
||||
/**
|
||||
-------------------------------
|
||||
-- Mixins
|
||||
-------------------------------
|
||||
**/
|
||||
/**
|
||||
-------------------------------
|
||||
-- Normalize
|
||||
-------------------------------
|
||||
**/
|
||||
h1, h2, h3 {
|
||||
color: #ebe5d4;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.75em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
html {
|
||||
line-height: 1.15;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
article,
|
||||
aside,
|
||||
footer,
|
||||
|
@ -34,62 +35,75 @@ nav,
|
|||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
figcaption,
|
||||
figure,
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
-webkit-text-decoration-skip: objects;
|
||||
}
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline-width: 0;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none;
|
||||
text-decoration: underline;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: inherit;
|
||||
font-weight: bolder;
|
||||
}
|
||||
code,
|
||||
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
mark {
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 60%;
|
||||
|
@ -97,31 +111,38 @@ sup {
|
|||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.55em;
|
||||
background: #bdcbdb;
|
||||
background: #151d26;
|
||||
color: #151d26;
|
||||
border-radius: 2px;
|
||||
padding: 0 2px 0 2px;
|
||||
margin: 0 2px 0 0;
|
||||
}
|
||||
|
||||
audio,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
|
@ -132,38 +153,44 @@ textarea {
|
|||
line-height: 1.15;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
button,
|
||||
html [type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
|
||||
button, html [type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner,
|
||||
|
||||
[type=button]::-moz-focus-inner,
|
||||
[type=reset]::-moz-focus-inner,
|
||||
[type=submit]::-moz-focus-inner,
|
||||
button::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring,
|
||||
|
||||
[type=button]:-moz-focusring,
|
||||
[type=reset]:-moz-focusring,
|
||||
[type=submit]:-moz-focusring,
|
||||
button:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
legend {
|
||||
box-sizing: border-box;
|
||||
color: inherit;
|
||||
|
@ -172,55 +199,143 @@ legend {
|
|||
padding: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
progress {
|
||||
display: inline-block;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
|
||||
[type=checkbox],
|
||||
[type=radio] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
|
||||
[type=number]::-webkit-inner-spin-button,
|
||||
[type=number]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
[type="search"] {
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
|
||||
[type=search]::-webkit-search-cancel-button,
|
||||
[type=search]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
details,
|
||||
menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
/**
|
||||
-------------------------------
|
||||
-- Main Structure
|
||||
-------------------------------
|
||||
**/
|
||||
|
||||
form {
|
||||
display: inline-block;
|
||||
}
|
||||
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;
|
||||
-moz-transition: all 0.3s linear;
|
||||
-webkit-transition: all 0.3s linear;
|
||||
-o-transition: all 0.3s linear;
|
||||
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 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -229,6 +344,7 @@ html {
|
|||
overflow: hidden;
|
||||
font: 400 1.2em/1.4em Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #ebe5d4;
|
||||
margin: 0;
|
||||
|
@ -240,51 +356,79 @@ body {
|
|||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #151d26;
|
||||
text-decoration: none;
|
||||
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;
|
||||
border-bottom: 1px solid #7ED07E;
|
||||
}
|
||||
a:hover {
|
||||
border-bottom: 1px solid #fc6399;
|
||||
border-bottom: 1px solid #FC6399;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #32302f;
|
||||
color: #7ed07e;
|
||||
color: #7ED07E;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #32302f;
|
||||
color: #7ed07e;
|
||||
color: #7ED07E;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
}
|
||||
pre code {
|
||||
color: #fc6399;
|
||||
|
||||
code {
|
||||
color: #FC6399;
|
||||
background: none;
|
||||
}
|
||||
|
||||
svg.icons {
|
||||
width: 25px;
|
||||
fill: #ebe5d4;
|
||||
}
|
||||
|
||||
header {
|
||||
background: #151d26;
|
||||
height: 90%;
|
||||
width: 100%;
|
||||
border-top: #ebe5d4 3px solid;
|
||||
}
|
||||
header #media {
|
||||
width: 100%;
|
||||
height: 90%;
|
||||
position: absolute;
|
||||
}
|
||||
header #media .slide {
|
||||
-moz-transition: all 0.7s linear;
|
||||
-webkit-transition: all 0.7s linear;
|
||||
-o-transition: all 0.7s linear;
|
||||
transition: all 0.7s linear;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
header #media .hide {
|
||||
opacity: 0;
|
||||
}
|
||||
header #media .show {
|
||||
opacity: 1;
|
||||
}
|
||||
header #media video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
header nav {
|
||||
width: 97%;
|
||||
margin: 10px auto;
|
||||
z-index: 1000;
|
||||
position: relative;
|
||||
color: #151d26;
|
||||
}
|
||||
header nav .left,
|
||||
header nav .right {
|
||||
header nav .left, header nav .right {
|
||||
width: 50%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
|
@ -302,7 +446,7 @@ header nav .right {
|
|||
text-align: right;
|
||||
}
|
||||
header nav .right a.menu-link {
|
||||
background: #fc6399;
|
||||
background: #FC6399;
|
||||
margin-bottom: 4px;
|
||||
padding: 3px;
|
||||
border-radius: 2px;
|
||||
|
@ -311,8 +455,9 @@ header nav .right a.menu-link {
|
|||
border-bottom: none;
|
||||
}
|
||||
header nav .right a.menu-link:hover {
|
||||
background: #feb1cc;
|
||||
background: #FC6399;
|
||||
}
|
||||
|
||||
.container {
|
||||
z-index: 2;
|
||||
background: #ebe5d4;
|
||||
|
@ -331,57 +476,47 @@ header nav .right a.menu-link:hover {
|
|||
color: #32302f;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.container article .index,
|
||||
.container article .page {
|
||||
.container article .index, .container article .page {
|
||||
padding: 0 0 15px 0;
|
||||
}
|
||||
.container article .index img,
|
||||
.container article .page img {
|
||||
.container article .index img, .container article .page img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.container article .index h1,
|
||||
.container article .page h1 {
|
||||
.container article .index h1, .container article .page h1 {
|
||||
color: #151d26;
|
||||
}
|
||||
.container article .index p,
|
||||
.container article .page p {
|
||||
.container article .index p, .container article .page p {
|
||||
font: 300 1.25em/1.6em Helvetica, Arial, sans-serif;
|
||||
}
|
||||
.container article .index .meta,
|
||||
.container article .page .meta {
|
||||
.container article .index .meta, .container article .page .meta {
|
||||
font: 500 0.8em/1.3em Helvetica, Arial, sans-serif;
|
||||
padding: 5px 0 0 0;
|
||||
border-top: 1px solid #151d26;
|
||||
background: #ede8d8;
|
||||
background: #ebe5d4;
|
||||
}
|
||||
.container article .index .meta a,
|
||||
.container article .page .meta a {
|
||||
.container article .index .meta a, .container article .page .meta a {
|
||||
font-size: 0.8em;
|
||||
font-weight: 400;
|
||||
}
|
||||
.container article .index .archive-item,
|
||||
.container article .page .archive-item {
|
||||
.container article .index .archive-item, .container article .page .archive-item {
|
||||
padding: 15px 0 20px 0;
|
||||
}
|
||||
.container article .index .archive-item span.year,
|
||||
.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-weight: 500;
|
||||
padding: 5px;
|
||||
display: block;
|
||||
color: #151d26;
|
||||
}
|
||||
.container article .index .archive-item .archive-month,
|
||||
.container article .page .archive-item .archive-month {
|
||||
.container article .index .archive-item .archive-month, .container article .page .archive-item .archive-month {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 30%;
|
||||
padding: 5px;
|
||||
}
|
||||
.container article .index .archive-item .archive-month span.month,
|
||||
.container article .page .archive-item .archive-month span.month {
|
||||
color: #fc6399;
|
||||
.container article .index .archive-item .archive-month span.month, .container article .page .archive-item .archive-month span.month {
|
||||
color: #FC6399;
|
||||
font-size: 1.5em;
|
||||
font-weight: 300;
|
||||
padding: 5px;
|
||||
|
@ -394,35 +529,31 @@ header nav .right a.menu-link:hover {
|
|||
.container section a {
|
||||
color: #ebe5d4;
|
||||
}
|
||||
.container section .index-lists,
|
||||
.container section .page-title {
|
||||
.container section .index-lists, .container section .page-title {
|
||||
max-width: 840px;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
padding: 20px 0 0 0;
|
||||
}
|
||||
.container section .index-lists span,
|
||||
.container section .page-title span {
|
||||
font: 600 2em/1.5 Helvetica, Arial, sans-serif;
|
||||
color: #ebe5d4;
|
||||
.container section .index-lists span, .container section .page-title span {
|
||||
font-size: 2em;
|
||||
color: #FC6399;
|
||||
font-weight: 400;
|
||||
}
|
||||
.container section .index-lists .recent,
|
||||
.container section .page-title .recent,
|
||||
.container section .index-lists .featured,
|
||||
.container section .page-title .featured {
|
||||
.container section .index-lists .recent, .container section .index-lists .featured, .container section .page-title .recent, .container section .page-title .featured {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
vertical-align: top;
|
||||
}
|
||||
.container section .index-lists label,
|
||||
.container section .page-title label {
|
||||
.container section .index-lists label, .container section .page-title label {
|
||||
background: #32302f;
|
||||
color: #ebe5d4;
|
||||
font-size: 1.5em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
footer {
|
||||
background: #e4dcc5;
|
||||
background: #ebe5d4;
|
||||
padding: 10px;
|
||||
color: #151d26;
|
||||
font-size: 0.8em;
|
||||
|
@ -435,121 +566,44 @@ footer .inner {
|
|||
max-width: 840px;
|
||||
}
|
||||
footer .inner a {
|
||||
color: #fc6399;
|
||||
color: #FC6399;
|
||||
}
|
||||
@media only screen and (max-width: 640px) {
|
||||
header nav {
|
||||
width: 98%;
|
||||
}
|
||||
header span {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
.container article .index .archive-item .archive-month,
|
||||
.container article .page .archive-item .archive-month {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
header nav {
|
||||
width: 98%;
|
||||
}
|
||||
@media only screen and (max-width: 480px) {
|
||||
header nav {
|
||||
width: 96%;
|
||||
}
|
||||
.container article .index,
|
||||
.container article .page {
|
||||
margin: 0;
|
||||
}
|
||||
.container article .index p,
|
||||
.container article .page p {
|
||||
font: 300 1em/1.6em Helvetica, Arial, sans-serif;
|
||||
}
|
||||
.container section .index-lists .recent,
|
||||
.container section .index-lists .featured {
|
||||
width: 100% !important;
|
||||
}
|
||||
header span {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
@media only screen and (max-width: 375px) {
|
||||
header nav {
|
||||
width: 95%;
|
||||
}
|
||||
.container article .index,
|
||||
.container article .page {
|
||||
margin: 0;
|
||||
}
|
||||
.container article .index p,
|
||||
.container article .page p {
|
||||
font: 300 0.9em/1.7em Helvetica, Arial, sans-serif;
|
||||
}
|
||||
.container article .index .archive-item .archive-month,
|
||||
.container article .page .archive-item .archive-month {
|
||||
width: 95%;
|
||||
}
|
||||
header .container article .index .archive-item .archive-month, header .container article .page .archive-item .archive-month {
|
||||
width: 45%;
|
||||
}
|
||||
/**
|
||||
-------------------------------
|
||||
-- Forms
|
||||
-------------------------------
|
||||
**/
|
||||
form {
|
||||
display: inline-block;
|
||||
|
||||
header nav {
|
||||
width: 96%;
|
||||
}
|
||||
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;
|
||||
header .container article .index, header .container article .page {
|
||||
margin: 0;
|
||||
}
|
||||
textarea {
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
color: $type02;
|
||||
font: 15px 'RobotoMono';
|
||||
header .container article .index p, header .container article .page p {
|
||||
font: 300 1em/1.6em Helvetica, Arial, sans-serif;
|
||||
}
|
||||
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;
|
||||
header .container section .index-lists .recent, header .container section .index-lists .featured {
|
||||
width: 100% !important;
|
||||
}
|
||||
button:hover,
|
||||
input[type=submit]:hover {
|
||||
background: #fc7ca9;
|
||||
|
||||
header nav {
|
||||
width: 95%;
|
||||
}
|
||||
select {
|
||||
font: 14px 'RobotoMono';
|
||||
border: 1px solid #fc6399;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
color: #151d26;
|
||||
|
||||
.container article .index, .container article .page {
|
||||
margin: 0;
|
||||
}
|
||||
::-webkit-input-placeholder {
|
||||
font: 14px 'RobotoMono';
|
||||
color: #837e7c;
|
||||
.container article .index p, .container article .page p {
|
||||
font: 300 0.9em/1.7em Helvetica, Arial, sans-serif;
|
||||
}
|
||||
:-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;
|
||||
.container article .index .archive-item .archive-month, .container article .page .archive-item .archive-month {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
/*# 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 |
2
content/themes/fipamo-default/assets/scripts/Start.js
Normal file
2
content/themes/fipamo-default/assets/scripts/Start.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
(()=>{class t{constructor(){this.start()}start(){console.log("Connected like F.E.")}}document.addEventListener("DOMContentLoaded",(function(){new t}),!1)})();
|
||||
//# sourceMappingURL=Start.js.map
|
|
@ -0,0 +1 @@
|
|||
{"mappings":"4BAKIA,KAAKC,QAEPA,QACEC,QAAQC,IAAI,wBCNhBC,SAASC,iBACP,oBACA,WACa,IAAIC,KAEjB","sources":["src/themes/theme-fipamo-default/com/Base.js","src/themes/theme-fipamo-default/com/Start.js"],"sourcesContent":["export default class Base {\n //--------------------------\n // constructor\n //--------------------------\n constructor() {\n this.start();\n }\n start() {\n console.log(\"Connected like F.E.\");\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","start","console","log","document","addEventListener","$b8d4b81eabebe07b$export$2e2bcd8739ae039"],"version":3,"file":"Start.js.map"}
|
583
content/themes/fipamo-default/assets/scripts/ThemeStart.js
Normal file
583
content/themes/fipamo-default/assets/scripts/ThemeStart.js
Normal file
|
@ -0,0 +1,583 @@
|
|||
// modules are defined as an array
|
||||
// [ module function, map of requires ]
|
||||
//
|
||||
// map of requires is short require name -> numeric require
|
||||
//
|
||||
// anything defined in a previous bundle is accessed via the
|
||||
// orig method which is the require for previous bundles
|
||||
|
||||
(function (modules, entry, mainEntry, parcelRequireName, globalName) {
|
||||
/* eslint-disable no-undef */
|
||||
var globalObject =
|
||||
typeof globalThis !== 'undefined'
|
||||
? globalThis
|
||||
: typeof self !== 'undefined'
|
||||
? self
|
||||
: typeof window !== 'undefined'
|
||||
? window
|
||||
: typeof global !== 'undefined'
|
||||
? global
|
||||
: {};
|
||||
/* eslint-enable no-undef */
|
||||
|
||||
// Save the require from previous bundle to this closure if any
|
||||
var previousRequire =
|
||||
typeof globalObject[parcelRequireName] === 'function' &&
|
||||
globalObject[parcelRequireName];
|
||||
|
||||
var cache = previousRequire.cache || {};
|
||||
// Do not use `require` to prevent Webpack from trying to bundle this call
|
||||
var nodeRequire =
|
||||
typeof module !== 'undefined' &&
|
||||
typeof module.require === 'function' &&
|
||||
module.require.bind(module);
|
||||
|
||||
function newRequire(name, jumped) {
|
||||
if (!cache[name]) {
|
||||
if (!modules[name]) {
|
||||
// if we cannot find the module within our internal map or
|
||||
// cache jump to the current global require ie. the last bundle
|
||||
// that was added to the page.
|
||||
var currentRequire =
|
||||
typeof globalObject[parcelRequireName] === 'function' &&
|
||||
globalObject[parcelRequireName];
|
||||
if (!jumped && currentRequire) {
|
||||
return currentRequire(name, true);
|
||||
}
|
||||
|
||||
// If there are other bundles on this page the require from the
|
||||
// previous one is saved to 'previousRequire'. Repeat this as
|
||||
// many times as there are bundles until the module is found or
|
||||
// we exhaust the require chain.
|
||||
if (previousRequire) {
|
||||
return previousRequire(name, true);
|
||||
}
|
||||
|
||||
// Try the node require function if it exists.
|
||||
if (nodeRequire && typeof name === 'string') {
|
||||
return nodeRequire(name);
|
||||
}
|
||||
|
||||
var err = new Error("Cannot find module '" + name + "'");
|
||||
err.code = 'MODULE_NOT_FOUND';
|
||||
throw err;
|
||||
}
|
||||
|
||||
localRequire.resolve = resolve;
|
||||
localRequire.cache = {};
|
||||
|
||||
var module = (cache[name] = new newRequire.Module(name));
|
||||
|
||||
modules[name][0].call(
|
||||
module.exports,
|
||||
localRequire,
|
||||
module,
|
||||
module.exports,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
return cache[name].exports;
|
||||
|
||||
function localRequire(x) {
|
||||
var res = localRequire.resolve(x);
|
||||
return res === false ? {} : newRequire(res);
|
||||
}
|
||||
|
||||
function resolve(x) {
|
||||
var id = modules[name][1][x];
|
||||
return id != null ? id : x;
|
||||
}
|
||||
}
|
||||
|
||||
function Module(moduleName) {
|
||||
this.id = moduleName;
|
||||
this.bundle = newRequire;
|
||||
this.exports = {};
|
||||
}
|
||||
|
||||
newRequire.isParcelRequire = true;
|
||||
newRequire.Module = Module;
|
||||
newRequire.modules = modules;
|
||||
newRequire.cache = cache;
|
||||
newRequire.parent = previousRequire;
|
||||
newRequire.register = function (id, exports) {
|
||||
modules[id] = [
|
||||
function (require, module) {
|
||||
module.exports = exports;
|
||||
},
|
||||
{},
|
||||
];
|
||||
};
|
||||
|
||||
Object.defineProperty(newRequire, 'root', {
|
||||
get: function () {
|
||||
return globalObject[parcelRequireName];
|
||||
},
|
||||
});
|
||||
|
||||
globalObject[parcelRequireName] = newRequire;
|
||||
|
||||
for (var i = 0; i < entry.length; i++) {
|
||||
newRequire(entry[i]);
|
||||
}
|
||||
|
||||
if (mainEntry) {
|
||||
// Expose entry point to Node, AMD or browser globals
|
||||
// Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
|
||||
var mainExports = newRequire(mainEntry);
|
||||
|
||||
// CommonJS
|
||||
if (typeof exports === 'object' && typeof module !== 'undefined') {
|
||||
module.exports = mainExports;
|
||||
|
||||
// RequireJS
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define(function () {
|
||||
return mainExports;
|
||||
});
|
||||
|
||||
// <script>
|
||||
} else if (globalName) {
|
||||
this[globalName] = mainExports;
|
||||
}
|
||||
}
|
||||
})({"5ZIt9":[function(require,module,exports) {
|
||||
"use strict";
|
||||
var HMR_HOST = null;
|
||||
var HMR_PORT = 1234;
|
||||
var HMR_SECURE = false;
|
||||
var HMR_ENV_HASH = "d6ea1d42532a7575";
|
||||
module.bundle.HMR_BUNDLE_ID = "423b0fbd795fbd6e";
|
||||
function _toConsumableArray(arr) {
|
||||
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
||||
}
|
||||
function _nonIterableSpread() {
|
||||
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
||||
}
|
||||
function _iterableToArray(iter) {
|
||||
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
||||
}
|
||||
function _arrayWithoutHoles(arr) {
|
||||
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
||||
}
|
||||
function _createForOfIteratorHelper(o, allowArrayLike) {
|
||||
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
|
||||
if (!it) {
|
||||
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
||||
if (it) o = it;
|
||||
var i = 0;
|
||||
var F = function F() {
|
||||
};
|
||||
return {
|
||||
s: F,
|
||||
n: function n() {
|
||||
if (i >= o.length) return {
|
||||
done: true
|
||||
};
|
||||
return {
|
||||
done: false,
|
||||
value: o[i++]
|
||||
};
|
||||
},
|
||||
e: function e(_e) {
|
||||
throw _e;
|
||||
},
|
||||
f: F
|
||||
};
|
||||
}
|
||||
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
||||
}
|
||||
var normalCompletion = true, didErr = false, err;
|
||||
return {
|
||||
s: function s() {
|
||||
it = it.call(o);
|
||||
},
|
||||
n: function n() {
|
||||
var step = it.next();
|
||||
normalCompletion = step.done;
|
||||
return step;
|
||||
},
|
||||
e: function e(_e2) {
|
||||
didErr = true;
|
||||
err = _e2;
|
||||
},
|
||||
f: function f() {
|
||||
try {
|
||||
if (!normalCompletion && it.return != null) it.return();
|
||||
} finally{
|
||||
if (didErr) throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
function _unsupportedIterableToArray(o, minLen) {
|
||||
if (!o) return;
|
||||
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
||||
var n = Object.prototype.toString.call(o).slice(8, -1);
|
||||
if (n === "Object" && o.constructor) n = o.constructor.name;
|
||||
if (n === "Map" || n === "Set") return Array.from(o);
|
||||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
||||
}
|
||||
function _arrayLikeToArray(arr, len) {
|
||||
if (len == null || len > arr.length) len = arr.length;
|
||||
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
||||
return arr2;
|
||||
}
|
||||
/* global HMR_HOST, HMR_PORT, HMR_ENV_HASH, HMR_SECURE */ /*::
|
||||
import type {
|
||||
HMRAsset,
|
||||
HMRMessage,
|
||||
} from '@parcel/reporter-dev-server/src/HMRServer.js';
|
||||
interface ParcelRequire {
|
||||
(string): mixed;
|
||||
cache: {|[string]: ParcelModule|};
|
||||
hotData: mixed;
|
||||
Module: any;
|
||||
parent: ?ParcelRequire;
|
||||
isParcelRequire: true;
|
||||
modules: {|[string]: [Function, {|[string]: string|}]|};
|
||||
HMR_BUNDLE_ID: string;
|
||||
root: ParcelRequire;
|
||||
}
|
||||
interface ParcelModule {
|
||||
hot: {|
|
||||
data: mixed,
|
||||
accept(cb: (Function) => void): void,
|
||||
dispose(cb: (mixed) => void): void,
|
||||
// accept(deps: Array<string> | string, cb: (Function) => void): void,
|
||||
// decline(): void,
|
||||
_acceptCallbacks: Array<(Function) => void>,
|
||||
_disposeCallbacks: Array<(mixed) => void>,
|
||||
|};
|
||||
}
|
||||
declare var module: {bundle: ParcelRequire, ...};
|
||||
declare var HMR_HOST: string;
|
||||
declare var HMR_PORT: string;
|
||||
declare var HMR_ENV_HASH: string;
|
||||
declare var HMR_SECURE: boolean;
|
||||
*/ var OVERLAY_ID = '__parcel__error__overlay__';
|
||||
var OldModule = module.bundle.Module;
|
||||
function Module(moduleName) {
|
||||
OldModule.call(this, moduleName);
|
||||
this.hot = {
|
||||
data: module.bundle.hotData,
|
||||
_acceptCallbacks: [],
|
||||
_disposeCallbacks: [],
|
||||
accept: function accept(fn) {
|
||||
this._acceptCallbacks.push(fn || function() {
|
||||
});
|
||||
},
|
||||
dispose: function dispose(fn) {
|
||||
this._disposeCallbacks.push(fn);
|
||||
}
|
||||
};
|
||||
module.bundle.hotData = undefined;
|
||||
}
|
||||
module.bundle.Module = Module;
|
||||
var checkedAssets, acceptedAssets, assetsToAccept;
|
||||
function getHostname() {
|
||||
return HMR_HOST || (location.protocol.indexOf('http') === 0 ? location.hostname : 'localhost');
|
||||
}
|
||||
function getPort() {
|
||||
return HMR_PORT || location.port;
|
||||
} // eslint-disable-next-line no-redeclare
|
||||
var parent = module.bundle.parent;
|
||||
if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {
|
||||
var hostname = getHostname();
|
||||
var port = getPort();
|
||||
var protocol = HMR_SECURE || location.protocol == 'https:' && !/localhost|127.0.0.1|0.0.0.0/.test(hostname) ? 'wss' : 'ws';
|
||||
var ws = new WebSocket(protocol + '://' + hostname + (port ? ':' + port : '') + '/'); // $FlowFixMe
|
||||
ws.onmessage = function(event) {
|
||||
checkedAssets = {
|
||||
};
|
||||
acceptedAssets = {
|
||||
};
|
||||
assetsToAccept = [];
|
||||
var data = JSON.parse(event.data);
|
||||
if (data.type === 'update') {
|
||||
// Remove error overlay if there is one
|
||||
if (typeof document !== 'undefined') removeErrorOverlay();
|
||||
var assets = data.assets.filter(function(asset) {
|
||||
return asset.envHash === HMR_ENV_HASH;
|
||||
}); // Handle HMR Update
|
||||
var handled = assets.every(function(asset) {
|
||||
return asset.type === 'css' || asset.type === 'js' && hmrAcceptCheck(module.bundle.root, asset.id, asset.depsByBundle);
|
||||
});
|
||||
if (handled) {
|
||||
console.clear();
|
||||
assets.forEach(function(asset) {
|
||||
hmrApply(module.bundle.root, asset);
|
||||
});
|
||||
for(var i = 0; i < assetsToAccept.length; i++){
|
||||
var id = assetsToAccept[i][1];
|
||||
if (!acceptedAssets[id]) hmrAcceptRun(assetsToAccept[i][0], id);
|
||||
}
|
||||
} else window.location.reload();
|
||||
}
|
||||
if (data.type === 'error') {
|
||||
// Log parcel errors to console
|
||||
var _iterator = _createForOfIteratorHelper(data.diagnostics.ansi), _step;
|
||||
try {
|
||||
for(_iterator.s(); !(_step = _iterator.n()).done;){
|
||||
var ansiDiagnostic = _step.value;
|
||||
var stack = ansiDiagnostic.codeframe ? ansiDiagnostic.codeframe : ansiDiagnostic.stack;
|
||||
console.error('🚨 [parcel]: ' + ansiDiagnostic.message + '\n' + stack + '\n\n' + ansiDiagnostic.hints.join('\n'));
|
||||
}
|
||||
} catch (err) {
|
||||
_iterator.e(err);
|
||||
} finally{
|
||||
_iterator.f();
|
||||
}
|
||||
if (typeof document !== 'undefined') {
|
||||
// Render the fancy html overlay
|
||||
removeErrorOverlay();
|
||||
var overlay = createErrorOverlay(data.diagnostics.html); // $FlowFixMe
|
||||
document.body.appendChild(overlay);
|
||||
}
|
||||
}
|
||||
};
|
||||
ws.onerror = function(e) {
|
||||
console.error(e.message);
|
||||
};
|
||||
ws.onclose = function() {
|
||||
console.warn('[parcel] 🚨 Connection to the HMR server was lost');
|
||||
};
|
||||
}
|
||||
function removeErrorOverlay() {
|
||||
var overlay = document.getElementById(OVERLAY_ID);
|
||||
if (overlay) {
|
||||
overlay.remove();
|
||||
console.log('[parcel] ✨ Error resolved');
|
||||
}
|
||||
}
|
||||
function createErrorOverlay(diagnostics) {
|
||||
var overlay = document.createElement('div');
|
||||
overlay.id = OVERLAY_ID;
|
||||
var errorHTML = '<div style="background: black; opacity: 0.85; font-size: 16px; color: white; position: fixed; height: 100%; width: 100%; top: 0px; left: 0px; padding: 30px; font-family: Menlo, Consolas, monospace; z-index: 9999;">';
|
||||
var _iterator2 = _createForOfIteratorHelper(diagnostics), _step2;
|
||||
try {
|
||||
for(_iterator2.s(); !(_step2 = _iterator2.n()).done;){
|
||||
var diagnostic = _step2.value;
|
||||
var stack = diagnostic.codeframe ? diagnostic.codeframe : diagnostic.stack;
|
||||
errorHTML += "\n <div>\n <div style=\"font-size: 18px; font-weight: bold; margin-top: 20px;\">\n \uD83D\uDEA8 ".concat(diagnostic.message, "\n </div>\n <pre>").concat(stack, "</pre>\n <div>\n ").concat(diagnostic.hints.map(function(hint) {
|
||||
return '<div>💡 ' + hint + '</div>';
|
||||
}).join(''), "\n </div>\n ").concat(diagnostic.documentation ? "<div>\uD83D\uDCDD <a style=\"color: violet\" href=\"".concat(diagnostic.documentation, "\" target=\"_blank\">Learn more</a></div>") : '', "\n </div>\n ");
|
||||
}
|
||||
} catch (err) {
|
||||
_iterator2.e(err);
|
||||
} finally{
|
||||
_iterator2.f();
|
||||
}
|
||||
errorHTML += '</div>';
|
||||
overlay.innerHTML = errorHTML;
|
||||
return overlay;
|
||||
}
|
||||
function getParents(bundle, id) /*: Array<[ParcelRequire, string]> */ {
|
||||
var modules = bundle.modules;
|
||||
if (!modules) return [];
|
||||
var parents = [];
|
||||
var k, d, dep;
|
||||
for(k in modules)for(d in modules[k][1]){
|
||||
dep = modules[k][1][d];
|
||||
if (dep === id || Array.isArray(dep) && dep[dep.length - 1] === id) parents.push([
|
||||
bundle,
|
||||
k
|
||||
]);
|
||||
}
|
||||
if (bundle.parent) parents = parents.concat(getParents(bundle.parent, id));
|
||||
return parents;
|
||||
}
|
||||
function updateLink(link) {
|
||||
var newLink = link.cloneNode();
|
||||
newLink.onload = function() {
|
||||
if (link.parentNode !== null) // $FlowFixMe
|
||||
link.parentNode.removeChild(link);
|
||||
};
|
||||
newLink.setAttribute('href', link.getAttribute('href').split('?')[0] + '?' + Date.now()); // $FlowFixMe
|
||||
link.parentNode.insertBefore(newLink, link.nextSibling);
|
||||
}
|
||||
var cssTimeout = null;
|
||||
function reloadCSS() {
|
||||
if (cssTimeout) return;
|
||||
cssTimeout = setTimeout(function() {
|
||||
var links = document.querySelectorAll('link[rel="stylesheet"]');
|
||||
for(var i = 0; i < links.length; i++){
|
||||
// $FlowFixMe[incompatible-type]
|
||||
var href = links[i].getAttribute('href');
|
||||
var hostname = getHostname();
|
||||
var servedFromHMRServer = hostname === 'localhost' ? new RegExp('^(https?:\\/\\/(0.0.0.0|127.0.0.1)|localhost):' + getPort()).test(href) : href.indexOf(hostname + ':' + getPort());
|
||||
var absolute = /^https?:\/\//i.test(href) && href.indexOf(window.location.origin) !== 0 && !servedFromHMRServer;
|
||||
if (!absolute) updateLink(links[i]);
|
||||
}
|
||||
cssTimeout = null;
|
||||
}, 50);
|
||||
}
|
||||
function hmrApply(bundle, asset) {
|
||||
var modules = bundle.modules;
|
||||
if (!modules) return;
|
||||
if (asset.type === 'css') reloadCSS();
|
||||
else if (asset.type === 'js') {
|
||||
var deps = asset.depsByBundle[bundle.HMR_BUNDLE_ID];
|
||||
if (deps) {
|
||||
if (modules[asset.id]) {
|
||||
// Remove dependencies that are removed and will become orphaned.
|
||||
// This is necessary so that if the asset is added back again, the cache is gone, and we prevent a full page reload.
|
||||
var oldDeps = modules[asset.id][1];
|
||||
for(var dep in oldDeps)if (!deps[dep] || deps[dep] !== oldDeps[dep]) {
|
||||
var id = oldDeps[dep];
|
||||
var parents = getParents(module.bundle.root, id);
|
||||
if (parents.length === 1) hmrDelete(module.bundle.root, id);
|
||||
}
|
||||
}
|
||||
var fn = new Function('require', 'module', 'exports', asset.output);
|
||||
modules[asset.id] = [
|
||||
fn,
|
||||
deps
|
||||
];
|
||||
} else if (bundle.parent) hmrApply(bundle.parent, asset);
|
||||
}
|
||||
}
|
||||
function hmrDelete(bundle, id1) {
|
||||
var modules = bundle.modules;
|
||||
if (!modules) return;
|
||||
if (modules[id1]) {
|
||||
// Collect dependencies that will become orphaned when this module is deleted.
|
||||
var deps = modules[id1][1];
|
||||
var orphans = [];
|
||||
for(var dep in deps){
|
||||
var parents = getParents(module.bundle.root, deps[dep]);
|
||||
if (parents.length === 1) orphans.push(deps[dep]);
|
||||
} // Delete the module. This must be done before deleting dependencies in case of circular dependencies.
|
||||
delete modules[id1];
|
||||
delete bundle.cache[id1]; // Now delete the orphans.
|
||||
orphans.forEach(function(id) {
|
||||
hmrDelete(module.bundle.root, id);
|
||||
});
|
||||
} else if (bundle.parent) hmrDelete(bundle.parent, id1);
|
||||
}
|
||||
function hmrAcceptCheck(bundle, id, depsByBundle) {
|
||||
if (hmrAcceptCheckOne(bundle, id, depsByBundle)) return true;
|
||||
// Traverse parents breadth first. All possible ancestries must accept the HMR update, or we'll reload.
|
||||
var parents = getParents(module.bundle.root, id);
|
||||
var accepted = false;
|
||||
while(parents.length > 0){
|
||||
var v = parents.shift();
|
||||
var a = hmrAcceptCheckOne(v[0], v[1], null);
|
||||
if (a) // If this parent accepts, stop traversing upward, but still consider siblings.
|
||||
accepted = true;
|
||||
else {
|
||||
// Otherwise, queue the parents in the next level upward.
|
||||
var p = getParents(module.bundle.root, v[1]);
|
||||
if (p.length === 0) {
|
||||
// If there are no parents, then we've reached an entry without accepting. Reload.
|
||||
accepted = false;
|
||||
break;
|
||||
}
|
||||
parents.push.apply(parents, _toConsumableArray(p));
|
||||
}
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
function hmrAcceptCheckOne(bundle, id, depsByBundle) {
|
||||
var modules = bundle.modules;
|
||||
if (!modules) return;
|
||||
if (depsByBundle && !depsByBundle[bundle.HMR_BUNDLE_ID]) {
|
||||
// If we reached the root bundle without finding where the asset should go,
|
||||
// there's nothing to do. Mark as "accepted" so we don't reload the page.
|
||||
if (!bundle.parent) return true;
|
||||
return hmrAcceptCheck(bundle.parent, id, depsByBundle);
|
||||
}
|
||||
if (checkedAssets[id]) return true;
|
||||
checkedAssets[id] = true;
|
||||
var cached = bundle.cache[id];
|
||||
assetsToAccept.push([
|
||||
bundle,
|
||||
id
|
||||
]);
|
||||
if (!cached || cached.hot && cached.hot._acceptCallbacks.length) return true;
|
||||
}
|
||||
function hmrAcceptRun(bundle, id) {
|
||||
var cached = bundle.cache[id];
|
||||
bundle.hotData = {
|
||||
};
|
||||
if (cached && cached.hot) cached.hot.data = bundle.hotData;
|
||||
if (cached && cached.hot && cached.hot._disposeCallbacks.length) cached.hot._disposeCallbacks.forEach(function(cb) {
|
||||
cb(bundle.hotData);
|
||||
});
|
||||
delete bundle.cache[id];
|
||||
bundle(id);
|
||||
cached = bundle.cache[id];
|
||||
if (cached && cached.hot && cached.hot._acceptCallbacks.length) cached.hot._acceptCallbacks.forEach(function(cb) {
|
||||
var assetsToAlsoAccept = cb(function() {
|
||||
return getParents(module.bundle.root, id);
|
||||
});
|
||||
if (assetsToAlsoAccept && assetsToAccept.length) // $FlowFixMe[method-unbinding]
|
||||
assetsToAccept.push.apply(assetsToAccept, assetsToAlsoAccept);
|
||||
});
|
||||
acceptedAssets[id] = true;
|
||||
}
|
||||
|
||||
},{}],"3OjfR":[function(require,module,exports) {
|
||||
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
||||
var _baseJs = require("./Base.js");
|
||||
var _baseJsDefault = parcelHelpers.interopDefault(_baseJs);
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var base = new _baseJsDefault.default();
|
||||
}, false);
|
||||
|
||||
},{"./Base.js":"jWciR","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"jWciR":[function(require,module,exports) {
|
||||
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
||||
parcelHelpers.defineInteropFlag(exports);
|
||||
class Base {
|
||||
//--------------------------
|
||||
// constructor
|
||||
//--------------------------
|
||||
constructor(){
|
||||
this.currentSlide = 0;
|
||||
this.slides = document.querySelectorAll("#media .slide");
|
||||
this.start();
|
||||
}
|
||||
start() {
|
||||
if (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";
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
exports.default = Base;
|
||||
|
||||
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"gkKU3":[function(require,module,exports) {
|
||||
exports.interopDefault = function(a) {
|
||||
return a && a.__esModule ? a : {
|
||||
default: a
|
||||
};
|
||||
};
|
||||
exports.defineInteropFlag = function(a) {
|
||||
Object.defineProperty(a, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
};
|
||||
exports.exportAll = function(source, dest) {
|
||||
Object.keys(source).forEach(function(key) {
|
||||
if (key === 'default' || key === '__esModule' || dest.hasOwnProperty(key)) return;
|
||||
Object.defineProperty(dest, key, {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return source[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
return dest;
|
||||
};
|
||||
exports.export = function(dest, destName, get) {
|
||||
Object.defineProperty(dest, destName, {
|
||||
enumerable: true,
|
||||
get: get
|
||||
});
|
||||
};
|
||||
|
||||
},{}]},["5ZIt9","3OjfR"], "3OjfR", "parcelRequire0e20")
|
||||
|
||||
//# sourceMappingURL=ThemeStart.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
{% if debug is defined %}
|
||||
{% set assetPath = '/src/themes/theme-fipamo-default/fipamo-default/assets/' %}
|
||||
{% set assetPath = '/src/themes/theme-'~theme~'/'~theme~'/assets/' %}
|
||||
{% else %}
|
||||
{% set assetPath = '/assets/' %}
|
||||
{% endif %}
|
||||
|
@ -15,15 +15,52 @@
|
|||
</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
||||
<meta name="keywords" content="{{ info['keywords'] }}"/>
|
||||
<meta name="keywords" content="{{ info['keywords'] }}" />
|
||||
<meta name="description" content="{{info['description']}} " />
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta property="og:image" content="{{info["image"]}}" />
|
||||
<meta name="twitter:image" content="{{info["image"]}}" />
|
||||
<link rel="stylesheet" type="text/css" href="{{ assetPath~"css/base.css?=adfafd" }}">
|
||||
<link rel="stylesheet" type="text/css" href="{{ assetPath~"css/base.css?=dfvbghh" }}">
|
||||
</head>
|
||||
<body>
|
||||
<!--
|
||||
<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>
|
||||
{% apply spaceless %}
|
||||
<div class="left">
|
||||
|
@ -43,7 +80,6 @@
|
|||
{% else %}
|
||||
<a href="{{"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -68,10 +104,9 @@
|
|||
{% else %}
|
||||
<a href="/archives.html">Archives</a><br />
|
||||
{% endif %}
|
||||
|
||||
© 2020 By Fipamo
|
||||
</div>
|
||||
</footer>
|
||||
<script src="{{ assetPath~"scripts/start.min.js" }}" type="text/javascript"></script>
|
||||
<script src="{{ assetPath~"scripts/ThemeStart.js" }}" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "fipamo-default/frame.twig" %}
|
||||
{% extends "frame.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{{ title }}
|
||||
|
@ -39,6 +39,7 @@
|
|||
{% else %}
|
||||
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
||||
{% endif %}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "fipamo-default/frame.twig" %}
|
||||
{% extends "frame.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{{ title }}
|
||||
|
@ -12,7 +12,7 @@
|
|||
</section>
|
||||
<article>
|
||||
<div class="page">
|
||||
THIS IS A CUSTOM TEMPLATE <br />
|
||||
[CUSTOM PAGE BRUH]
|
||||
<p>{{content | raw}}</p>
|
||||
<div>
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
|||
<strong>tags: </strong>
|
||||
{% for tag in meta['tags'] %}
|
||||
{% if dynamicRender is defined %}
|
||||
{% if dynamicRender == 'true' %}
|
||||
{% if dynamicRender == 'false' %}
|
||||
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
||||
{% else %}
|
||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||
|
@ -28,7 +28,6 @@
|
|||
{% else %}
|
||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "fipamo-default/frame.twig" %}
|
||||
{% extends "frame.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{{ title }}
|
||||
|
@ -19,7 +19,7 @@
|
|||
<strong>tags: </strong>
|
||||
{% for tag in meta['tags'] %}
|
||||
{% if dynamicRender is defined %}
|
||||
{% if dynamicRender == 'false' %}
|
||||
{% if dynamicRender == 'true' %}
|
||||
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
||||
{% else %}
|
||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||
|
@ -27,7 +27,6 @@
|
|||
{% else %}
|
||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "fipamo-default/frame.twig" %}
|
||||
{% extends "frame.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{{ title }}
|
||||
|
@ -23,7 +23,6 @@
|
|||
{% else %}
|
||||
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
|
257
package-lock.json
generated
257
package-lock.json
generated
|
@ -25,9 +25,10 @@
|
|||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.16.5",
|
||||
"babel-cli": "^6.26.0",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"parcel": "^2.0.1"
|
||||
"parcel": "^2.0.1",
|
||||
"prettier": "^2.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
|
@ -1819,15 +1820,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz",
|
||||
"integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
|
||||
"integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^9.2.0",
|
||||
"espree": "^9.3.1",
|
||||
"globals": "^13.9.0",
|
||||
"ignore": "^4.0.6",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"minimatch": "^3.0.4",
|
||||
|
@ -1838,9 +1839,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
||||
"version": "13.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
|
||||
"integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
|
||||
"version": "13.13.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
|
||||
"integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
|
||||
"dependencies": {
|
||||
"type-fest": "^0.20.2"
|
||||
},
|
||||
|
@ -1851,14 +1852,6 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/ignore": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/type-fest": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
|
@ -3908,14 +3901,6 @@
|
|||
"resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.1.tgz",
|
||||
"integrity": "sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A=="
|
||||
},
|
||||
"node_modules/ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
|
@ -6618,17 +6603,6 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/enquirer": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
|
||||
"integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
|
||||
"dependencies": {
|
||||
"ansi-colors": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
|
||||
|
@ -6755,23 +6729,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz",
|
||||
"integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==",
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz",
|
||||
"integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==",
|
||||
"dependencies": {
|
||||
"@eslint/eslintrc": "^1.0.5",
|
||||
"@eslint/eslintrc": "^1.2.1",
|
||||
"@humanwhocodes/config-array": "^0.9.2",
|
||||
"ajv": "^6.10.0",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.2",
|
||||
"debug": "^4.3.2",
|
||||
"doctrine": "^3.0.0",
|
||||
"enquirer": "^2.3.5",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^7.1.0",
|
||||
"eslint-scope": "^7.1.1",
|
||||
"eslint-utils": "^3.0.0",
|
||||
"eslint-visitor-keys": "^3.1.0",
|
||||
"espree": "^9.2.0",
|
||||
"eslint-visitor-keys": "^3.3.0",
|
||||
"espree": "^9.3.1",
|
||||
"esquery": "^1.4.0",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
@ -6779,7 +6752,7 @@
|
|||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^6.0.1",
|
||||
"globals": "^13.6.0",
|
||||
"ignore": "^4.0.6",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"is-glob": "^4.0.0",
|
||||
|
@ -6790,9 +6763,7 @@
|
|||
"minimatch": "^3.0.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.1",
|
||||
"progress": "^2.0.0",
|
||||
"regexpp": "^3.2.0",
|
||||
"semver": "^7.2.1",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"strip-json-comments": "^3.1.0",
|
||||
"text-table": "^0.2.0",
|
||||
|
@ -6947,9 +6918,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/eslint-scope": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz",
|
||||
"integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
|
||||
"integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^5.2.0"
|
||||
|
@ -6959,9 +6930,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/eslint-visitor-keys": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
|
||||
"integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
|
||||
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
|
@ -7007,14 +6978,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/ignore": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
|
@ -7078,20 +7041,6 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
|
@ -7170,13 +7119,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz",
|
||||
"integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==",
|
||||
"version": "9.3.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
|
||||
"integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
|
||||
"dependencies": {
|
||||
"acorn": "^8.6.0",
|
||||
"acorn": "^8.7.0",
|
||||
"acorn-jsx": "^5.3.1",
|
||||
"eslint-visitor-keys": "^3.1.0"
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -7194,9 +7143,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/espree/node_modules/eslint-visitor-keys": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
|
||||
"integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
|
||||
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
|
@ -8505,7 +8454,6 @@
|
|||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
|
@ -9627,6 +9575,7 @@
|
|||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
|
@ -11558,6 +11507,21 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz",
|
||||
"integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prismjs": {
|
||||
"version": "1.25.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz",
|
||||
|
@ -11586,14 +11550,6 @@
|
|||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
|
@ -14376,7 +14332,8 @@
|
|||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "1.10.2",
|
||||
|
@ -15645,15 +15602,15 @@
|
|||
}
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz",
|
||||
"integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
|
||||
"integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==",
|
||||
"requires": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^9.2.0",
|
||||
"espree": "^9.3.1",
|
||||
"globals": "^13.9.0",
|
||||
"ignore": "^4.0.6",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"minimatch": "^3.0.4",
|
||||
|
@ -15661,18 +15618,13 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"globals": {
|
||||
"version": "13.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
|
||||
"integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
|
||||
"version": "13.13.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
|
||||
"integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
|
||||
"requires": {
|
||||
"type-fest": "^0.20.2"
|
||||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
|
@ -17091,11 +17043,6 @@
|
|||
"resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.1.tgz",
|
||||
"integrity": "sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A=="
|
||||
},
|
||||
"ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA=="
|
||||
},
|
||||
"ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
|
@ -19391,14 +19338,6 @@
|
|||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
|
||||
"dev": true
|
||||
},
|
||||
"enquirer": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
|
||||
"integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
|
||||
"requires": {
|
||||
"ansi-colors": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
|
||||
|
@ -19497,23 +19436,22 @@
|
|||
}
|
||||
},
|
||||
"eslint": {
|
||||
"version": "8.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz",
|
||||
"integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==",
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz",
|
||||
"integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==",
|
||||
"requires": {
|
||||
"@eslint/eslintrc": "^1.0.5",
|
||||
"@eslint/eslintrc": "^1.2.1",
|
||||
"@humanwhocodes/config-array": "^0.9.2",
|
||||
"ajv": "^6.10.0",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.2",
|
||||
"debug": "^4.3.2",
|
||||
"doctrine": "^3.0.0",
|
||||
"enquirer": "^2.3.5",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^7.1.0",
|
||||
"eslint-scope": "^7.1.1",
|
||||
"eslint-utils": "^3.0.0",
|
||||
"eslint-visitor-keys": "^3.1.0",
|
||||
"espree": "^9.2.0",
|
||||
"eslint-visitor-keys": "^3.3.0",
|
||||
"espree": "^9.3.1",
|
||||
"esquery": "^1.4.0",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
@ -19521,7 +19459,7 @@
|
|||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^6.0.1",
|
||||
"globals": "^13.6.0",
|
||||
"ignore": "^4.0.6",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"is-glob": "^4.0.0",
|
||||
|
@ -19532,9 +19470,7 @@
|
|||
"minimatch": "^3.0.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.1",
|
||||
"progress": "^2.0.0",
|
||||
"regexpp": "^3.2.0",
|
||||
"semver": "^7.2.1",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"strip-json-comments": "^3.1.0",
|
||||
"text-table": "^0.2.0",
|
||||
|
@ -19592,18 +19528,18 @@
|
|||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz",
|
||||
"integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
|
||||
"integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
|
||||
"requires": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^5.2.0"
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
|
||||
"integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA=="
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
|
||||
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA=="
|
||||
},
|
||||
"estraverse": {
|
||||
"version": "5.3.0",
|
||||
|
@ -19631,11 +19567,6 @@
|
|||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||
},
|
||||
"ignore": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
|
@ -19681,14 +19612,6 @@
|
|||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
|
@ -19779,13 +19702,13 @@
|
|||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw=="
|
||||
},
|
||||
"espree": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz",
|
||||
"integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==",
|
||||
"version": "9.3.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
|
||||
"integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
|
||||
"requires": {
|
||||
"acorn": "^8.6.0",
|
||||
"acorn": "^8.7.0",
|
||||
"acorn-jsx": "^5.3.1",
|
||||
"eslint-visitor-keys": "^3.1.0"
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
|
@ -19794,9 +19717,9 @@
|
|||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
|
||||
"integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA=="
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
|
||||
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -20802,8 +20725,7 @@
|
|||
"ignore": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ=="
|
||||
},
|
||||
"immutable": {
|
||||
"version": "4.0.0",
|
||||
|
@ -21658,6 +21580,7 @@
|
|||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
|
@ -23110,6 +23033,12 @@
|
|||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz",
|
||||
"integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==",
|
||||
"dev": true
|
||||
},
|
||||
"prismjs": {
|
||||
"version": "1.25.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz",
|
||||
|
@ -23132,11 +23061,6 @@
|
|||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"dev": true
|
||||
},
|
||||
"progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
|
@ -25353,7 +25277,8 @@
|
|||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"yaml": {
|
||||
"version": "1.10.2",
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.16.5",
|
||||
"babel-cli": "^6.26.0",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"parcel": "^2.0.1"
|
||||
"parcel": "^2.0.1",
|
||||
"prettier": "^2.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.16.5",
|
||||
|
|
|
@ -1912,6 +1912,7 @@ a {
|
|||
font: 300 1em Helvetica, Arial, sans-serif;
|
||||
color: #b2cce5;
|
||||
text-decoration: underline;
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
|
||||
svg.icons {
|
||||
|
@ -1953,21 +1954,8 @@ svg.icons {
|
|||
-moz-animation: spin 2s linear infinite;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
@-moz-keyframes spin {
|
||||
100% {
|
||||
-moz-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes spin {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
#notifications #notifyMessage .notify-icon {
|
||||
background: #32302f;
|
||||
|
@ -2057,10 +2045,7 @@ svg.icons {
|
|||
border-radius: 50px;
|
||||
}
|
||||
.main-container section header #wrapper #right #dash-menu a button svg {
|
||||
-moz-transition: all 0.1s linear;
|
||||
-webkit-transition: all 0.1s linear;
|
||||
-o-transition: all 0.1s linear;
|
||||
transition: all 0.1s linear;
|
||||
transition: all 0.2s linear;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
fill: #EFEBE3;
|
||||
|
@ -2270,15 +2255,12 @@ svg.icons {
|
|||
margin-left: 10px;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list .recent-header .index-header-right a button svg {
|
||||
-moz-transition: all 0.1s linear;
|
||||
-webkit-transition: all 0.1s linear;
|
||||
-o-transition: all 0.1s linear;
|
||||
transition: all 0.1s linear;
|
||||
transition: all 0.2s linear;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
fill: #EFEBE3;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link {
|
||||
font-size: 1.5em;
|
||||
font-weight: 300;
|
||||
display: inline-block;
|
||||
|
@ -2286,8 +2268,15 @@ svg.icons {
|
|||
vertical-align: top;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link label {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link .post-video, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link .post-video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link label, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link label {
|
||||
font-size: 1.4em;
|
||||
font-weight: 700;
|
||||
color: #EFEBE3;
|
||||
|
@ -2301,53 +2290,53 @@ svg.icons {
|
|||
top: 35%;
|
||||
text-shadow: 2px 2px 0 #32302f;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.65) 100%);
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 50%;
|
||||
position: relative;
|
||||
background: none;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left button {
|
||||
border-radius: 3px;
|
||||
background: #1D3040;
|
||||
margin: 0 0 10px 10px;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button svg {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button svg, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left button svg {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
fill: #b2cce5;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left .item-options {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left .item-options, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left .item-options {
|
||||
border-radius: 3px;
|
||||
margin: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=false] {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=false], #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left button[data-active=false] {
|
||||
background: #1D3040;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=false] svg {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=false] svg, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left button[data-active=false] svg {
|
||||
fill: #b2cce5;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=true] {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=true], #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left button[data-active=true] {
|
||||
background: #f5ab35;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=true] svg {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-left button[data-active=true] svg, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-left button[data-active=true] svg {
|
||||
fill: #1D3040;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-right {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-right, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-right {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
}
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-right span {
|
||||
#dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-link div#options #option-right span, #dash-index-content #dash-index #dash-index-wrapper #dash-recent #recent-list a.post-video-link div#options #option-right span {
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
background: #EFEBE3;
|
||||
|
@ -2845,9 +2834,6 @@ button, input[type=submit] {
|
|||
cursor: pointer;
|
||||
border: 0;
|
||||
padding: 10px 0 5px 0;
|
||||
-moz-transition: all 0.3s linear;
|
||||
-webkit-transition: all 0.3s linear;
|
||||
-o-transition: all 0.3s linear;
|
||||
transition: all 0.3s linear;
|
||||
}
|
||||
|
||||
|
@ -2911,7 +2897,8 @@ select {
|
|||
margin-left: 10px;
|
||||
width: 55px;
|
||||
}
|
||||
#post-index #post-index-wrapper #post-index-header #post-index-header-right a button svg {
|
||||
#post-index #post-index-wrapper #post-index-header #post-index-header-right a svg {
|
||||
transition: all 0.1s linear;
|
||||
width: 20px;
|
||||
height: 17px;
|
||||
fill: #EFEBE3;
|
||||
|
@ -2942,13 +2929,17 @@ select {
|
|||
vertical-align: top;
|
||||
width: 100%;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg, #post-index #post-index-wrapper #posts-list a.page-link div.page-video {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
background-color: #fc6399;
|
||||
position: relative;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg label {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg video, #post-index #post-index-wrapper #posts-list a.page-link div.page-video video {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg label, #post-index #post-index-wrapper #posts-list a.page-link div.page-video label {
|
||||
font-size: 2em;
|
||||
font-weight: 700;
|
||||
color: #EFEBE3;
|
||||
|
@ -2961,9 +2952,8 @@ select {
|
|||
position: relative;
|
||||
top: 35%;
|
||||
text-shadow: 2px 2px 0 #32302f;
|
||||
text-shadow: 2px 2px 0 #32302f;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta {
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.65) 100%);
|
||||
border-radius: 3px;
|
||||
|
@ -2972,51 +2962,52 @@ select {
|
|||
position: absolute;
|
||||
padding: 0 0 20px 0;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options {
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 50%;
|
||||
position: relative;
|
||||
background: none;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left button {
|
||||
border-radius: 3px;
|
||||
background: #1D3040;
|
||||
margin: 0 0 10px 10px;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button svg {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left svg, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left svg {
|
||||
transition: all 0.2s linear;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
fill: #b2cce5;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left .item-options {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left .item-options, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left .item-options {
|
||||
border-radius: 3px;
|
||||
margin: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=false] {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=false], #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left button[data-active=false] {
|
||||
background: #1D3040;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=false] svg {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=false] svg, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left button[data-active=false] svg {
|
||||
fill: #b2cce5;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=true] {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=true], #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left button[data-active=true] {
|
||||
background: #f5ab35;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=true] svg {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-left button[data-active=true] svg, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-left button[data-active=true] svg {
|
||||
fill: #1D3040;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-right {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-right, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-right {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
}
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-right span {
|
||||
#post-index #post-index-wrapper #posts-list a.page-link div.page-bg #meta #options #option-right span, #post-index #post-index-wrapper #posts-list a.page-link div.page-video #meta #options #option-right span {
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
background: #EFEBE3;
|
||||
|
@ -3138,13 +3129,6 @@ select {
|
|||
#post-edit-index #post-edit-index-wrapper #post-header #post-header-wrapper #post-meta #post-options button {
|
||||
width: 25%;
|
||||
height: 45px;
|
||||
-moz-transition: all 0.3s linear;
|
||||
-webkit-transition: all 0.3s linear;
|
||||
-o-transition: all 0.3s linear;
|
||||
transition: all 0.3s linear;
|
||||
-moz-transition: all 0.3s linear;
|
||||
-webkit-transition: all 0.3s linear;
|
||||
-o-transition: all 0.3s linear;
|
||||
transition: all 0.3s linear;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
|
@ -3164,41 +3148,88 @@ select {
|
|||
#post-edit-index #post-edit-index-wrapper #post-header #post-header-wrapper #post-meta #post-options button[data-active=true] svg {
|
||||
fill: #1D3040;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-header #post-header-wrapper #post-meta #featured-image-upload, #post-edit-index #post-edit-index-wrapper #post-header #post-header-wrapper #post-meta #post-image-upload {
|
||||
#post-edit-index #post-edit-index-wrapper #post-header #post-header-wrapper #post-meta #page-files-upload, #post-edit-index #post-edit-index-wrapper #post-header #post-header-wrapper #post-meta #post-image-upload {
|
||||
display: none;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature {
|
||||
width: 100%;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #featured-image-drop {
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager {
|
||||
background: #f5ab35;
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper {
|
||||
width: 100%;
|
||||
max-width: 900px;
|
||||
padding: 10px;
|
||||
margin: 0 auto;
|
||||
font-weight: bold;
|
||||
font-color: #1D3040;
|
||||
font-size: 1em;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-file-drop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
background: black;
|
||||
min-height: 100px;
|
||||
background: #EFEBE3;
|
||||
color: #1D3040;
|
||||
vertical-align: middle;
|
||||
font-family: "Lucida Console", Monaco, monospace;
|
||||
border-radius: 5px;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #featured-image-drop label {
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-file-drop label {
|
||||
cursor: pointer;
|
||||
font-weight: 600px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #featured-image-drop img {
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-file-drop img {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #featured-new-image-btn {
|
||||
position: absolute;
|
||||
margin: 20px;
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-images-list, #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list {
|
||||
padding: 10px 0 0 0;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #featured-new-image-btn #new-feature-upload {
|
||||
padding-top: 4px;
|
||||
background: #EFEBE3;
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-images-list .img-item, #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list .img-item {
|
||||
height: 150px;
|
||||
width: 23.8%;
|
||||
border-radius: 3px;
|
||||
margin: 0 10px 10px 0;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #featured-new-image-btn #new-feature-upload svg {
|
||||
fill: #fc6399;
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-images-list .audio-item, #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list .audio-item {
|
||||
height: 150px;
|
||||
width: 23.8%;
|
||||
border-radius: 3px;
|
||||
margin: 0 10px 10px 0;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
background: #1D3040;
|
||||
background: url("/assets/images/global/upload-audio.png") no-repeat center center/cover;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-images-list .video-item, #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list .video-item {
|
||||
height: 150px;
|
||||
width: 23.8%;
|
||||
border-radius: 3px;
|
||||
margin: 0 10px 10px 0;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
background: #1D3040;
|
||||
background: url("/assets/images/global/upload-video.png") no-repeat center center/cover;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-images-list .file-item, #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list .file-item {
|
||||
height: 150px;
|
||||
width: 23.8%;
|
||||
border-radius: 3px;
|
||||
margin: 0 10px 10px 0;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
background: #1D3040;
|
||||
background: url("/assets/images/global/upload-doc.png") no-repeat center center/cover;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #edit-post {
|
||||
width: 100%;
|
||||
|
@ -3216,7 +3247,6 @@ select {
|
|||
border-color: #fc6399;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #edit, #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight {
|
||||
/* Both elements need the same text and space styling so they are directly on top of each other */
|
||||
border: 0;
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
|
@ -3248,6 +3278,28 @@ select {
|
|||
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight {
|
||||
z-index: 0;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight pre {
|
||||
margin: 0;
|
||||
}
|
||||
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight pre code {
|
||||
font-family: "Lucida Console", Monaco, monospace;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
line-height: 1.6em;
|
||||
font-size: 1.25em;
|
||||
color: #fde3a7;
|
||||
word-wrap: normal;
|
||||
white-space: pre-wrap;
|
||||
line-break: normal;
|
||||
-webkit-line-break: normal;
|
||||
-o-line-break: normal;
|
||||
-moz-line-break: normal;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
max-width: 900px;
|
||||
min-height: 200px;
|
||||
caret-color: #fc6399;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
#post-edit-index #post-edit-index-wrapper #post-header #post-title #post-date {
|
||||
|
@ -3630,9 +3682,6 @@ select {
|
|||
background: #b2cce5;
|
||||
width: 10%;
|
||||
height: 39px;
|
||||
-moz-transition: all 0.3s linear;
|
||||
-webkit-transition: all 0.3s linear;
|
||||
-o-transition: all 0.3s linear;
|
||||
transition: all 0.3s linear;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
|
|
33
public/assets/images/global/the-logo.svg
Normal file
33
public/assets/images/global/the-logo.svg
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 486 678" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="Logo" transform="matrix(1.36867,0,0,1.36867,-351.696,-71.9183)">
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,-99.4797)">
|
||||
<path d="M93.67,140.92L93.67,140.921C105.569,140.921 115.216,150.567 115.216,162.467L115.216,172.724L115.216,172.724L115.216,182.262C115.216,194.161 105.569,203.808 93.669,203.808C81.976,203.217 74.12,195.969 72.237,184.474L72.282,182.737L72.282,162.467L72.205,160.847C72.775,149.587 82.728,141.121 93.67,140.92Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,-437.697)">
|
||||
<path d="M93.67,211.678L93.67,211.678C105.569,211.678 115.216,221.324 115.216,233.224L115.216,243.481L115.216,243.481L115.216,253.019C115.216,264.919 105.569,274.565 93.669,274.565C81.976,273.975 74.12,266.726 72.237,255.232L72.282,253.495L72.282,233.224L72.205,231.604C72.775,220.344 82.728,211.878 93.67,211.678Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,241.338)">
|
||||
<path d="M93.67,69.288L93.67,69.288C105.569,69.288 115.216,78.934 115.216,90.834L115.216,101.091L115.216,101.091L115.216,110.629C115.216,122.528 105.569,132.175 93.669,132.175C81.976,131.584 74.12,124.336 72.237,112.842L72.282,111.105L72.282,90.834L72.205,89.214C72.775,77.954 82.728,69.488 93.67,69.288Z" style="fill:rgb(171,183,183);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,-104.112)">
|
||||
<path d="M38.059,142.92L38.059,142.921C49.958,142.921 59.605,152.567 59.605,164.467L59.605,174.724L59.605,174.724L59.605,184.262C59.605,196.161 49.958,205.808 38.058,205.808C26.365,205.217 18.509,197.969 16.626,186.474L16.671,184.737L16.671,164.467L16.594,162.847C17.164,151.587 27.117,143.121 38.059,142.92Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,-104.112)">
|
||||
<path d="M148.331,142.92L148.331,142.921C160.23,142.921 169.877,152.567 169.877,164.467L169.877,174.724L169.877,174.724L169.877,184.262C169.877,196.161 160.23,205.808 148.331,205.808C136.637,205.217 128.782,197.969 126.898,186.474L126.943,184.737L126.943,164.467L126.867,162.847C127.436,151.587 137.389,143.121 148.331,142.92Z" style="fill:rgb(171,183,183);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,-437.697)">
|
||||
<path d="M38.059,211.678L38.059,211.678C49.958,211.678 59.605,221.324 59.605,233.224L59.605,243.481L59.605,243.481L59.605,253.019C59.605,264.919 49.958,274.565 38.058,274.565C26.365,273.975 18.509,266.726 16.626,255.232L16.671,253.495L16.671,233.224L16.594,231.604C17.164,220.344 27.117,211.878 38.059,211.678Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,-437.697)">
|
||||
<path d="M148.331,211.678L148.331,211.678C160.23,211.678 169.877,221.324 169.877,233.224L169.877,243.481L169.877,243.481L169.877,253.019C169.877,264.919 160.23,274.565 148.331,274.565C136.637,273.975 128.782,266.726 126.898,255.232L126.943,253.495L126.943,233.224L126.867,231.604C127.436,220.344 137.389,211.878 148.331,211.678Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,241.338)">
|
||||
<path d="M38.059,69.288L38.059,69.288C49.958,69.288 59.605,78.934 59.605,90.834L59.605,101.091L59.605,101.091L59.605,110.629C59.605,122.528 49.958,132.175 38.058,132.175C26.365,131.584 18.509,124.336 16.626,112.842L16.671,111.105L16.671,90.834L16.594,89.214C17.164,77.954 27.117,69.488 38.059,69.288Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.31599,0,0,2.31599,218.53,241.338)">
|
||||
<path d="M148.331,69.288L148.331,69.288C160.23,69.288 169.877,78.934 169.877,90.834L169.877,101.091L169.877,101.091L169.877,110.629C169.877,122.528 160.23,132.175 148.331,132.175C136.637,131.584 128.782,124.336 126.898,112.842L126.943,111.105L126.943,90.834L126.867,89.214C127.436,77.954 137.389,69.488 148.331,69.288Z" style="fill:rgb(171,183,183);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
BIN
public/assets/images/global/upload-audio.png
Normal file
BIN
public/assets/images/global/upload-audio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8 KiB |
BIN
public/assets/images/global/upload-doc.png
Normal file
BIN
public/assets/images/global/upload-doc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
public/assets/images/global/upload-video.png
Normal file
BIN
public/assets/images/global/upload-video.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
File diff suppressed because one or more lines are too long
11
public/assets/scripts/dash.min.js
vendored
11
public/assets/scripts/dash.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
require "../vendor/autoload.php";
|
||||
include "../brain/App.inc.php";
|
||||
|
||||
use brain\init\App as App;
|
||||
|
||||
new App();
|
||||
|
|
204
src/com/ui/FileManager.js
Normal file
204
src/com/ui/FileManager.js
Normal file
|
@ -0,0 +1,204 @@
|
|||
import Sortable from 'sortablejs';
|
||||
import DataUtils from '../utils/DataUtils';
|
||||
import Notfications from './Notifications.js';
|
||||
const notify = new Notfications();
|
||||
|
||||
export default class FileManager {
|
||||
//--------------------------
|
||||
// constructor
|
||||
//--------------------------
|
||||
constructor(upload, input, imageList, fileList) {
|
||||
this.upload = upload;
|
||||
this.input = input;
|
||||
this.imageList = imageList;
|
||||
this.fileList = fileList;
|
||||
this.accetableFiles = [
|
||||
'image/jpeg',
|
||||
'image/gif',
|
||||
'image/png',
|
||||
'image/svg',
|
||||
'audio/mpeg',
|
||||
'video/mp4',
|
||||
'application/pdf',
|
||||
'text/plain',
|
||||
'text/rtf'
|
||||
];
|
||||
this.files = [];
|
||||
this.sortedFiles = [];
|
||||
this.storage = [];
|
||||
this.start();
|
||||
}
|
||||
//--------------------------
|
||||
// methods
|
||||
//--------------------------
|
||||
start() {
|
||||
this.upload.addEventListener('dragover', e => this.handleFileActions(e), false);
|
||||
this.upload.addEventListener('drop', e => this.handleFileActions(e), false);
|
||||
this.input.addEventListener('change', e => this.handleFileActions(e), false);
|
||||
|
||||
Sortable.create(this.imageList, {
|
||||
onUpdate: e => {
|
||||
notify.alert('REINDEXING FILES', null);
|
||||
let currentFiles = []; //store current list
|
||||
let items = e.target.children;
|
||||
for (let index = 0; index < items.length; index++) {
|
||||
var item = items[index];
|
||||
let url = '';
|
||||
if (item.className == 'img-item') {
|
||||
url = item.style.backgroundImage.slice(4, -1).replace(/"/g, '');
|
||||
} else {
|
||||
url = item.getAttribute('data-source');
|
||||
}
|
||||
|
||||
currentFiles.push({
|
||||
earl: url
|
||||
});
|
||||
}
|
||||
this.reindexFiles(currentFiles, 0);
|
||||
}
|
||||
});
|
||||
|
||||
Sortable.create(this.fileList, {
|
||||
onUpdate: e => {
|
||||
notify.alert('REINDEXING FILES', null);
|
||||
let currentFiles = [];
|
||||
let items = e.target.children;
|
||||
for (let index = 0; index < items.length; index++) {
|
||||
var item = items[index];
|
||||
let url = item.getAttribute('data-source');
|
||||
currentFiles.push({
|
||||
earl: url
|
||||
});
|
||||
}
|
||||
this.reindexFiles(currentFiles, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getFiles() {
|
||||
return this.files;
|
||||
}
|
||||
|
||||
reindexFiles(sortOrder, step) {
|
||||
let count = sortOrder.length;
|
||||
if (step == 0) this.files = [];
|
||||
var utils = new DataUtils();
|
||||
var path = sortOrder[step].earl.split('/');
|
||||
utils.imgLoad(sortOrder[step].earl).then(blob => {
|
||||
var fresh = new File([blob], path[6], { type: blob.type });
|
||||
this.files.push(fresh);
|
||||
if (this.files.length <= count - 1) {
|
||||
this.reindexFiles(sortOrder, ++step);
|
||||
} else {
|
||||
notify.alert('FILES READY TO UPLOAD', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sortFiles(files) {
|
||||
var self = this;
|
||||
this.files = []; //clear files array
|
||||
this.imageList.innerHTML = '';
|
||||
this.fileList.innerHTML = '';
|
||||
for (var i = 0, file; (file = files[i]); i++) {
|
||||
var reader = new FileReader();
|
||||
// Closure to capture the file information
|
||||
|
||||
reader.onload = (theFile => {
|
||||
return function (f) {
|
||||
// sort files
|
||||
switch (theFile.type) {
|
||||
case 'image/jpg':
|
||||
case 'image/jpeg':
|
||||
case 'image/gif':
|
||||
case 'image/svg':
|
||||
case 'image/png':
|
||||
//create element and add to list
|
||||
var image = document.createElement('img');
|
||||
image.src = f.target.result;
|
||||
image.title = escape(theFile.name);
|
||||
var span = document.createElement('div');
|
||||
span.style.background =
|
||||
'url(' +
|
||||
f.target.result +
|
||||
') no-repeat center center / cover';
|
||||
span.className = 'img-item';
|
||||
image.setAttribute('id', i);
|
||||
self.storage.push([
|
||||
{
|
||||
id: 'page_image' + i,
|
||||
data: f.target.result,
|
||||
type: theFile.type,
|
||||
name: escape(theFile.name)
|
||||
}
|
||||
]);
|
||||
self.imageList.appendChild(span);
|
||||
//add to files list
|
||||
self.files.push(theFile);
|
||||
|
||||
break;
|
||||
case 'video/mp4':
|
||||
var video = document.createElement('div');
|
||||
video.className = 'video-item';
|
||||
video.setAttribute('data-source', f.target.result);
|
||||
self.imageList.appendChild(video);
|
||||
self.files.push(theFile);
|
||||
break;
|
||||
case 'audio/mpeg':
|
||||
var sound = document.createElement('div');
|
||||
sound.className = 'audio-item';
|
||||
sound.setAttribute('data-source', f.target.result);
|
||||
self.fileList.appendChild(sound);
|
||||
self.files.push(theFile);
|
||||
break;
|
||||
case 'application/pdf':
|
||||
case 'text/plain':
|
||||
case 'text/rtf':
|
||||
var file = document.createElement('div');
|
||||
file.className = 'file-item';
|
||||
file.setAttribute('data-source', f.target.result);
|
||||
self.fileList.appendChild(file);
|
||||
self.files.push(theFile);
|
||||
break;
|
||||
}
|
||||
};
|
||||
})(file);
|
||||
// Read in the image file as a data URL.
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------
|
||||
// event handlers
|
||||
//--------------------------
|
||||
handleFileActions(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
let self = this;
|
||||
let rawList = [];
|
||||
let sortedList = [];
|
||||
let notOnTheList = [];
|
||||
|
||||
switch (e.type) {
|
||||
case 'dragover':
|
||||
e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
|
||||
break;
|
||||
case 'change':
|
||||
case 'drop':
|
||||
e.type == 'drop'
|
||||
? (rawList = e.dataTransfer.files)
|
||||
: (rawList = e.target.files);
|
||||
for (var i = 0, f; (f = rawList[i]); i++) {
|
||||
// check witch files are cool to upload
|
||||
if (this.accetableFiles.includes(f.type)) {
|
||||
sortedList.push(f);
|
||||
} else {
|
||||
notOnTheList.push(f);
|
||||
}
|
||||
}
|
||||
//send for sorting
|
||||
self.sortFiles(sortedList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue