forked from projects/fipamo
respeced class imports to psr-4 standard, fixed asset moving, upgraded theme rendering
This commit is contained in:
parent
1351b98ee4
commit
8ad3fa38c5
72 changed files with 3602 additions and 11287 deletions
|
@ -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,9 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace brain\controller;
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Slim\Views\Twig;
|
use Slim\Views\Twig;
|
||||||
|
use brain\data\Book;
|
||||||
include "../brain/data/Book.inc.php";
|
use brain\data\Session;
|
||||||
|
use brain\data\Settings;
|
||||||
|
use brain\data\Themes;
|
||||||
|
use brain\utility\Setup;
|
||||||
|
|
||||||
class DashControl
|
class DashControl
|
||||||
{
|
{
|
||||||
|
@ -79,6 +85,7 @@ class DashControl
|
||||||
$data = (new Book())->getPages($currentPage, 4, $filter);
|
$data = (new Book())->getPages($currentPage, 4, $filter);
|
||||||
$template = "dash/book.twig";
|
$template = "dash/book.twig";
|
||||||
$pageOptions = [
|
$pageOptions = [
|
||||||
|
"title" => "Contents",
|
||||||
"entryCount" => $data["entryCount"],
|
"entryCount" => $data["entryCount"],
|
||||||
"numOfPages" => $data["numOfPages"],
|
"numOfPages" => $data["numOfPages"],
|
||||||
"currentPage" => $currentPage,
|
"currentPage" => $currentPage,
|
||||||
|
@ -135,7 +142,7 @@ class DashControl
|
||||||
"token" => Session::get("form_token"),
|
"token" => Session::get("form_token"),
|
||||||
"status" => Session::active(),
|
"status" => Session::active(),
|
||||||
"images" => $images,
|
"images" => $images,
|
||||||
"files"=>$files,
|
"files" => $files,
|
||||||
"views" => $views,
|
"views" => $views,
|
||||||
];
|
];
|
||||||
break;
|
break;
|
|
@ -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,46 +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":
|
|
||||||
//$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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
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,5 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace brain\data;
|
||||||
|
|
||||||
|
use brain\data\Contents;
|
||||||
|
use brain\data\Settings;
|
||||||
|
use brain\utility\DocTools;
|
||||||
|
|
||||||
use function _\filter;
|
use function _\filter;
|
||||||
use function _\find;
|
use function _\find;
|
||||||
|
|
||||||
|
@ -32,8 +38,8 @@ class Book
|
||||||
{
|
{
|
||||||
$content = $this->getContents();
|
$content = $this->getContents();
|
||||||
if ($task == "delete") {
|
if ($task == "delete") {
|
||||||
//$parsed = json_decode(file_get_contents("php://input"), true);
|
//$parsed = json_decode(file_get_contents("php://input"), true);
|
||||||
//$body = find($content, ["uuid" => $parsed["id"]]);
|
//$body = find($content, ["uuid" => $parsed["id"]]);
|
||||||
$body = $request->getParsedBody();
|
$body = $request->getParsedBody();
|
||||||
} else {
|
} else {
|
||||||
$body = $request->getParsedBody();
|
$body = $request->getParsedBody();
|
||||||
|
@ -59,7 +65,7 @@ class Book
|
||||||
if (isset($files["page_files"])) {
|
if (isset($files["page_files"])) {
|
||||||
$imageList = "";
|
$imageList = "";
|
||||||
$fileList = "";
|
$fileList = "";
|
||||||
//var_dump($files["page_files"] );
|
//var_dump($files["page_files"] );
|
||||||
foreach ($files["page_files"] as $file) {
|
foreach ($files["page_files"] as $file) {
|
||||||
$type = $file->getClientMediaType();
|
$type = $file->getClientMediaType();
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
|
@ -69,7 +75,7 @@ class Book
|
||||||
case "image/svg":
|
case "image/svg":
|
||||||
$imagesPath = "/assets/images/blog/" . $path . "/";
|
$imagesPath = "/assets/images/blog/" . $path . "/";
|
||||||
$imageList =
|
$imageList =
|
||||||
$imageList . $imagesPath . urlencode($file->getClientFileName()). ", ";
|
$imageList . $imagesPath . urlencode($file->getClientFileName()) . ", ";
|
||||||
|
|
||||||
FileUploader::uploadFile(
|
FileUploader::uploadFile(
|
||||||
"../public/assets/images/blog/" . $path . "/",
|
"../public/assets/images/blog/" . $path . "/",
|
||||||
|
@ -88,7 +94,7 @@ class Book
|
||||||
break;
|
break;
|
||||||
case "audio/mpeg":
|
case "audio/mpeg":
|
||||||
$soundPath = "/assets/sound/blog/" . $path . "/";
|
$soundPath = "/assets/sound/blog/" . $path . "/";
|
||||||
$fileList = $fileList . $soundPath . urlencode($file->getClientFileName()). ", ";
|
$fileList = $fileList . $soundPath . urlencode($file->getClientFileName()) . ", ";
|
||||||
|
|
||||||
FileUploader::uploadFile(
|
FileUploader::uploadFile(
|
||||||
"../public/assets/sound/blog/" . $path . "/",
|
"../public/assets/sound/blog/" . $path . "/",
|
||||||
|
@ -99,7 +105,7 @@ class Book
|
||||||
case 'text/plain':
|
case 'text/plain':
|
||||||
case 'text/rtf':
|
case 'text/rtf':
|
||||||
$docPath = "/assets/docs/blog/" . $path . "/";
|
$docPath = "/assets/docs/blog/" . $path . "/";
|
||||||
$fileList = $fileList . $docPath . urlencode($file->getClientFileName()). ", ";
|
$fileList = $fileList . $docPath . urlencode($file->getClientFileName()) . ", ";
|
||||||
|
|
||||||
FileUploader::uploadFile(
|
FileUploader::uploadFile(
|
||||||
"../public/assets/docs/blog/" . $path . "/",
|
"../public/assets/docs/blog/" . $path . "/",
|
||||||
|
@ -108,8 +114,8 @@ class Book
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$page_feature = $imageList;
|
$page_feature = $imageList;
|
||||||
$page_files = $fileList;
|
$page_files = $fileList;
|
||||||
} else {
|
} else {
|
||||||
//if no files, just reset string from page object
|
//if no files, just reset string from page object
|
||||||
$page_feature = $page["feature"];
|
$page_feature = $page["feature"];
|
||||||
|
@ -131,10 +137,10 @@ class Book
|
||||||
: new \Moment\Moment();
|
: new \Moment\Moment();
|
||||||
$updated = new \Moment\Moment();
|
$updated = new \Moment\Moment();
|
||||||
|
|
||||||
//grab current index from settings and update
|
//grab current index from settings and update
|
||||||
$id = $task != "create" ? $body["id"] : Settings::getCurrentIndex();
|
$id = $task != "create" ? $body["id"] : Settings::getCurrentIndex();
|
||||||
$uuid = $task != "create" ? $body["uuid"] : StringTools::createUUID();
|
$uuid = $task != "create" ? $body["uuid"] : StringTools::createUUID();
|
||||||
// now that variables are done, set to body object and then convert to markdown to save
|
// now that variables are done, set to body object and then convert to markdown to save
|
||||||
|
|
||||||
$body["id"] = $id;
|
$body["id"] = $id;
|
||||||
$body["uuid"] = $uuid;
|
$body["uuid"] = $uuid;
|
||||||
|
@ -148,7 +154,7 @@ class Book
|
||||||
|
|
||||||
$write = DocTools::objectToMD($body);
|
$write = DocTools::objectToMD($body);
|
||||||
|
|
||||||
// if layout is index, change path to file
|
// if layout is index, change path to file
|
||||||
|
|
||||||
if ($body["layout"] == "index") {
|
if ($body["layout"] == "index") {
|
||||||
$writePath = "../content/pages/start/index.md";
|
$writePath = "../content/pages/start/index.md";
|
||||||
|
@ -163,8 +169,9 @@ class Book
|
||||||
$settings = $config->getSettings();
|
$settings = $config->getSettings();
|
||||||
$message = "";
|
$message = "";
|
||||||
|
|
||||||
if ($settings["global"]["renderOnSave"] == "true" &&
|
if (
|
||||||
$settings["global"]["dynamicRender"] == "false"
|
$settings["global"]["renderOnSave"] == "true" &&
|
||||||
|
$settings["global"]["dynamicRender"] == "false"
|
||||||
) {
|
) {
|
||||||
$render = new Render();
|
$render = new Render();
|
||||||
$render->renderTags();
|
$render->renderTags();
|
||||||
|
@ -181,16 +188,16 @@ class Book
|
||||||
"id" => $uuid,
|
"id" => $uuid,
|
||||||
];
|
];
|
||||||
|
|
||||||
//TODO: When form submission is successful, make new form token
|
//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
|
//Session token doesn't reset on the front end, so turning this off for now
|
||||||
//$form_token = md5(uniqid(microtime(), true));
|
//$form_token = md5(uniqid(microtime(), true));
|
||||||
//Session::set("form_token", $form_token);
|
//Session::set("form_token", $form_token);
|
||||||
|
|
||||||
//once saved, update menu
|
//once saved, update menu
|
||||||
$body["path"] = $path;
|
$body["path"] = $path;
|
||||||
Settings::updateMenu($body);
|
Settings::updateMenu($body);
|
||||||
Settings::updateTags();
|
Settings::updateTags();
|
||||||
//if new page added, update current index in Settings file
|
//if new page added, update current index in Settings file
|
||||||
if ($task == "create") {
|
if ($task == "create") {
|
||||||
Settings::updateIndex();
|
Settings::updateIndex();
|
||||||
}
|
}
|
||||||
|
@ -216,7 +223,7 @@ class Book
|
||||||
return $item["deleted"] == true;
|
return $item["deleted"] == true;
|
||||||
});
|
});
|
||||||
|
|
||||||
//$all = $content;
|
//$all = $content;
|
||||||
$all = filter($content, function ($item) {
|
$all = filter($content, function ($item) {
|
||||||
return $item["deleted"] == false;
|
return $item["deleted"] == false;
|
||||||
});
|
});
|
||||||
|
@ -248,7 +255,7 @@ class Book
|
||||||
if (isset($filtered[$i + $range])) {
|
if (isset($filtered[$i + $range])) {
|
||||||
array_push($folder, $filtered[$i + $range]);
|
array_push($folder, $filtered[$i + $range]);
|
||||||
} else {
|
} else {
|
||||||
//chill out
|
//chill out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,8 +288,8 @@ class Book
|
||||||
}
|
}
|
||||||
public function getContents()
|
public function getContents()
|
||||||
{
|
{
|
||||||
//test new contents data class
|
//test new contents data class
|
||||||
//$new = (new Contents("../content/pages"))->getAll();
|
//$new = (new Contents("../content/pages"))->getAll();
|
||||||
$contents = (new Contents("../content/pages"))->getAll();
|
$contents = (new Contents("../content/pages"))->getAll();
|
||||||
return $contents;
|
return $contents;
|
||||||
}
|
}
|
|
@ -1,4 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace brain\data;
|
||||||
|
|
||||||
use League\CommonMark\Environment\Environment;
|
use League\CommonMark\Environment\Environment;
|
||||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||||
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
|
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
|
||||||
|
@ -7,7 +10,6 @@ use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
|
||||||
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
|
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
|
||||||
use League\CommonMark\MarkdownConverter;
|
use League\CommonMark\MarkdownConverter;
|
||||||
use League\CommonMark\CommonMarkConverter;
|
use League\CommonMark\CommonMarkConverter;
|
||||||
|
|
||||||
use HtmlSanitizer\Extension\Basic\BasicExtension;
|
use HtmlSanitizer\Extension\Basic\BasicExtension;
|
||||||
use HtmlSanitizer\Extension\Iframe\IframeExtension;
|
use HtmlSanitizer\Extension\Iframe\IframeExtension;
|
||||||
use HtmlSanitizer\SanitizerBuilder;
|
use HtmlSanitizer\SanitizerBuilder;
|
||||||
|
@ -26,7 +28,7 @@ class Contents
|
||||||
{
|
{
|
||||||
$folders = glob("$folder/*", GLOB_ONLYDIR);
|
$folders = glob("$folder/*", GLOB_ONLYDIR);
|
||||||
foreach ($folders as $folder) {
|
foreach ($folders as $folder) {
|
||||||
//$this->files[] = $folder . "/";
|
//$this->files[] = $folder . "/";
|
||||||
$this->read($folder);
|
$this->read($folder);
|
||||||
}
|
}
|
||||||
$files = array_filter(glob("$folder/*md"), "is_file");
|
$files = array_filter(glob("$folder/*md"), "is_file");
|
||||||
|
@ -35,45 +37,45 @@ class Contents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAll()
|
public function getAll()
|
||||||
{
|
{
|
||||||
$environment = new Environment($this->config);
|
$environment = new Environment($this->config);
|
||||||
$environment->addExtension(new CommonMarkCoreExtension());
|
$environment->addExtension(new CommonMarkCoreExtension());
|
||||||
|
|
||||||
// Add the extension
|
// Add the extension
|
||||||
$environment->addExtension(new FrontMatterExtension());
|
$environment->addExtension(new FrontMatterExtension());
|
||||||
|
|
||||||
//Add Strikethrough rendering
|
//Add Strikethrough rendering
|
||||||
$environment->addExtension(new StrikethroughExtension());
|
$environment->addExtension(new StrikethroughExtension());
|
||||||
|
|
||||||
//add attributes to elements in markdown
|
//add attributes to elements in markdown
|
||||||
$environment->addExtension(new AttributesExtension());
|
$environment->addExtension(new AttributesExtension());
|
||||||
|
|
||||||
// Instantiate the converter engine and start converting some Markdown!
|
// Instantiate the converter engine and start converting some Markdown!
|
||||||
$converter = new MarkdownConverter($environment);
|
$converter = new MarkdownConverter($environment);
|
||||||
|
|
||||||
$contents = [];
|
$contents = [];
|
||||||
foreach ($this->files as $file) {
|
foreach ($this->files as $file) {
|
||||||
//get meta and html from file
|
//get meta and html from file
|
||||||
$result = $converter->convertToHtml(file_get_contents($file));
|
$result = $converter->convertToHtml(file_get_contents($file));
|
||||||
$meta = [];
|
$meta = [];
|
||||||
if ($result instanceof RenderedContentWithFrontMatter) {
|
if ($result instanceof RenderedContentWithFrontMatter) {
|
||||||
$meta = $result->getFrontMatter();
|
$meta = $result->getFrontMatter();
|
||||||
}
|
}
|
||||||
|
|
||||||
//get raw markdown from file
|
//get raw markdown from file
|
||||||
$frontMatterExtension = new FrontMatterExtension();
|
$frontMatterExtension = new FrontMatterExtension();
|
||||||
$parsed = $frontMatterExtension
|
$parsed = $frontMatterExtension
|
||||||
->getFrontMatterParser()
|
->getFrontMatterParser()
|
||||||
->parse(file_get_contents($file));
|
->parse(file_get_contents($file));
|
||||||
|
|
||||||
//never trust the front end. clean it up
|
//never trust the front end. clean it up
|
||||||
|
|
||||||
$builder = new SanitizerBuilder();
|
$builder = new SanitizerBuilder();
|
||||||
$builder->registerExtension(new BasicExtension());
|
$builder->registerExtension(new BasicExtension());
|
||||||
$builder->registerExtension(new IframeExtension());
|
$builder->registerExtension(new IframeExtension());
|
||||||
|
|
||||||
//relative-a and relative-image
|
//relative-a and relative-image
|
||||||
$builder->registerExtension(
|
$builder->registerExtension(
|
||||||
new \HtmlSanitizer\Extension\Relative\A\AExtension()
|
new \HtmlSanitizer\Extension\Relative\A\AExtension()
|
||||||
);
|
);
|
||||||
|
@ -108,14 +110,14 @@ class Contents
|
||||||
$fileList = [];
|
$fileList = [];
|
||||||
$docs = '';
|
$docs = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$media = [];
|
$media = [];
|
||||||
$files = [];
|
$files = [];
|
||||||
foreach ($featureList as $file) {
|
foreach ($featureList as $file) {
|
||||||
$item = trim($file);
|
$item = trim($file);
|
||||||
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
||||||
if ($item != null || $item != "") {
|
if ($item != null || $item != "") {
|
||||||
array_push($media, ["file"=>$item, "type"=>trim($ext)]);
|
array_push($media, ["file" => $item, "type" => trim($ext)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,11 +125,11 @@ class Contents
|
||||||
$item = trim($file);
|
$item = trim($file);
|
||||||
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
$ext = pathinfo($item, PATHINFO_EXTENSION);
|
||||||
if ($item != null || $item != "") {
|
if ($item != null || $item != "") {
|
||||||
array_push($files, ["file"=>$item, "type"=>trim($ext)]);
|
array_push($files, ["file" => $item, "type" => trim($ext)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//sort attributes into page object
|
//sort attributes into page object
|
||||||
$page = [
|
$page = [
|
||||||
"id" => $meta["id"],
|
"id" => $meta["id"],
|
||||||
"uuid" => $meta["uuid"],
|
"uuid" => $meta["uuid"],
|
||||||
|
@ -153,9 +155,9 @@ class Contents
|
||||||
"content" => $parsed->getContent(),
|
"content" => $parsed->getContent(),
|
||||||
"html" => $scrubbed,
|
"html" => $scrubbed,
|
||||||
"media" => $media,
|
"media" => $media,
|
||||||
"docs"=>$files
|
"docs" => $files
|
||||||
];
|
];
|
||||||
//checks for duplicates
|
//checks for duplicates
|
||||||
$uuid = $meta["uuid"];
|
$uuid = $meta["uuid"];
|
||||||
$found = current(
|
$found = current(
|
||||||
array_filter($contents, function ($item) use ($uuid) {
|
array_filter($contents, function ($item) use ($uuid) {
|
||||||
|
@ -163,9 +165,9 @@ class Contents
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// if uuid is not present, add it
|
// if uuid is not present, add it
|
||||||
if (!$found) {
|
if (!$found) {
|
||||||
array_push($contents, $page);
|
array_push($contents, $page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$contents = orderBy($contents, ["id"], ["desc"]);
|
$contents = orderBy($contents, ["id"], ["desc"]);
|
|
@ -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,181 +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();
|
|
||||||
//TODO: Add theme folder to loader
|
|
||||||
$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
|
|
||||||
//TODO: change to just grab directory contents for scripts and css
|
|
||||||
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,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace brain\utility;
|
||||||
|
|
||||||
class DocTools
|
class DocTools
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
@ -11,7 +13,7 @@ class DocTools
|
||||||
try {
|
try {
|
||||||
if ($task == "create") {
|
if ($task == "create") {
|
||||||
if (!is_dir("../content/pages/" . $path)) {
|
if (!is_dir("../content/pages/" . $path)) {
|
||||||
//Directory does not exist, so lets create it.
|
//Directory does not exist, so lets create it.
|
||||||
mkdir("../content/pages/" . $path, 0755, true);
|
mkdir("../content/pages/" . $path, 0755, true);
|
||||||
}
|
}
|
||||||
file_put_contents($fileLocation, $fileContents);
|
file_put_contents($fileLocation, $fileContents);
|
|
@ -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 . "/" . 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
35
brain/utility/FileUploader.php
Normal file
35
brain/utility/FileUploader.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace brain\utility
|
||||||
|
|
||||||
|
use Psr\Http\Message\UploadedFileInterface;
|
||||||
|
|
||||||
|
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 . "/" . 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
|
<?php
|
||||||
|
|
||||||
class handleCors
|
namespace brain\utility;
|
||||||
|
|
||||||
|
use brain\data\Settings;
|
||||||
|
|
||||||
|
class HandleCors
|
||||||
{
|
{
|
||||||
public function __construct()
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
97
brain/utility/Mailer.php
Normal file
97
brain/utility/Mailer.php
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace brain\utility;
|
||||||
|
|
||||||
|
use Slim\Views\Twig;
|
||||||
|
use PHPMailer\PHPMailer\PHPMailer;
|
||||||
|
use PHPMailer\PHPMailer\Exception;
|
||||||
|
use brain\data\Settings;
|
||||||
|
|
||||||
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
227
brain/utility/Setup.php
Normal file
227
brain/utility/Setup.php
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
<?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",
|
||||||
|
"path" => "content/pages/start",
|
||||||
|
"layout" => "index",
|
||||||
|
"tags" => "start, welcome",
|
||||||
|
"author" => $handle,
|
||||||
|
"created" => $now->format("Y-m-d\TH:i:sP"),
|
||||||
|
"updated" => $now->format("Y-m-d\TH:i:sP"),
|
||||||
|
"deleted" => "false",
|
||||||
|
"slug" => "first",
|
||||||
|
"menu" => "false",
|
||||||
|
"featured" => "false",
|
||||||
|
"published" => "true",
|
||||||
|
"content" =>
|
||||||
|
"# F**k Yes \n\nIf you're seeing this, you're up and running. NICE WORK!\n\nFrom here, feel free to start dropping pages to your heart's content.\n\nFor some tips about using Fipamo, check out the ![docs](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage)\n\nAll good? Feel free to edit this page to whatever you want!\n\nYOU'RE THE CAPTAIN NOW.",
|
||||||
|
];
|
||||||
|
|
||||||
|
$freshIndex = DocTools::objectToMD($index);
|
||||||
|
|
||||||
|
//once all files created, write down
|
||||||
|
|
||||||
|
DocTools::writeSettings("../config/settings.json", $newSettings);
|
||||||
|
DocTools::writeSettings("../config/folks.json", $newFolks);
|
||||||
|
DocTools::writeSettings("../config/tags.json", []);
|
||||||
|
DocTools::writePages(
|
||||||
|
"create",
|
||||||
|
"start",
|
||||||
|
"../content/pages/start/index.md",
|
||||||
|
$freshIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
//if there is an older session file, get rid of it
|
||||||
|
if (is_file("../content/.session")) {
|
||||||
|
unlink("../content/.session");
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = ["type" => "blogInitGood", "message" => "Site Created"];
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function restore($request)
|
||||||
|
{
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "Still working on it.",
|
||||||
|
];
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
|
||||||
|
$backup = $request->getUploadedFiles();
|
||||||
|
$file = $backup["backup-upload"];
|
||||||
|
$size = $file->getSize();
|
||||||
|
$name = $file->getClientFileName();
|
||||||
|
|
||||||
|
//park it so it can be read
|
||||||
|
$file->moveTo("../content" . "/" . $name);
|
||||||
|
|
||||||
|
//open it and get files to verify user
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
if ($zip->open("../content" . "/" . $name) === true) {
|
||||||
|
$folks = json_decode($zip->getFromName("settings/folks.json"), true);
|
||||||
|
$found = find($folks, ["handle" => $body["restore_member_handle"]]);
|
||||||
|
|
||||||
|
//if member is found in back up, check pass
|
||||||
|
if ($found) {
|
||||||
|
if (password_verify($body["restore_member_pass"], $found["password"])) {
|
||||||
|
//backup verified, restore site
|
||||||
|
|
||||||
|
//set new secret key for older folks configs
|
||||||
|
$newFolks = [];
|
||||||
|
if (!isset($found["secret"])) {
|
||||||
|
$found["secret"] = StringTools::randomString(12);
|
||||||
|
}
|
||||||
|
array_push($newFolks, $found);
|
||||||
|
//dump files in folder
|
||||||
|
$zip->extractTo("../content");
|
||||||
|
|
||||||
|
//move to appropriate spots
|
||||||
|
/*
|
||||||
|
rename(
|
||||||
|
"../content/settings/settings.json",
|
||||||
|
"../config/settings.json"
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//load up old config file
|
||||||
|
$newConfig = json_decode(
|
||||||
|
file_get_contents("../content/settings/settings.json"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
//check for key, add if not there
|
||||||
|
if (!isset($newConfig["global"]["externalAPI"])) {
|
||||||
|
$newConfig["global"]["externalAPI"] = "false";
|
||||||
|
}
|
||||||
|
//write new config file
|
||||||
|
DocTools::writeSettings("../config/settings.json", $newConfig);
|
||||||
|
|
||||||
|
//rename("../content/settings/folks.json", "../config/folks.json");
|
||||||
|
DocTools::writeSettings("../config/folks.json", $newFolks);
|
||||||
|
|
||||||
|
rename("../content/settings/tags.json", "../config/tags.json");
|
||||||
|
|
||||||
|
//images path for blog and user
|
||||||
|
$blogImagePath = "../public/assets/images/blog";
|
||||||
|
$userImagePath = "../public/assets/images/user";
|
||||||
|
|
||||||
|
//check to see if image dirs are empty, if not chill
|
||||||
|
if ($globs = glob($blogImagePath . "/*")) {
|
||||||
|
//directory not empty, relax
|
||||||
|
} else {
|
||||||
|
rename("../content/public/assets/images/blog", $blogImagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($globs = glob($userImagePath . "/*")) {
|
||||||
|
//directory not empty, relax
|
||||||
|
} else {
|
||||||
|
rename("../content/public/assets/images/user", $userImagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
rename("../content/content/pages/", "../content/pages");
|
||||||
|
|
||||||
|
//legacy check for old file structure
|
||||||
|
if (is_file("../content/pages/index.md")) {
|
||||||
|
if (!is_dir("../content/pages/start")) {
|
||||||
|
//Directory does not exist, so lets create it.
|
||||||
|
mkdir("../content/pages/start", 0755, true);
|
||||||
|
//move start page to appropriate spot
|
||||||
|
rename(
|
||||||
|
"../content/pages/index.md",
|
||||||
|
"../content/pages/start/index.md"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//chill
|
||||||
|
}
|
||||||
|
|
||||||
|
//clean up
|
||||||
|
|
||||||
|
DocTools::deleteFolder("../content/settings");
|
||||||
|
DocTools::deleteFolder("../content/public");
|
||||||
|
DocTools::deleteFolder("../content/content");
|
||||||
|
$result = [
|
||||||
|
"type" => "requestGood",
|
||||||
|
"message" => "Site Restored! Redirecting",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "Check that password, champ.",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "No member found by that name, hoss",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
$zipPath = "../content/" . $name;
|
||||||
|
//trash zip when done
|
||||||
|
unlink($zipPath);
|
||||||
|
} else {
|
||||||
|
$result = [
|
||||||
|
"type" => "requestLame",
|
||||||
|
"message" => "Could not open backup. RATS!",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,10 +62,9 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<a class="page-link" href="/dashboard/page/edit/{{ page.uuid }}">
|
<a class="page-link" href="/dashboard/page/edit/{{ page.uuid }}">
|
||||||
<div class="page-bg" style="background: url({{ page.feature }}) no-repeat center center / cover">
|
<div class="page-bg" style="background: url({{ page.media[0].file }}) no-repeat center center / cover">
|
||||||
<label>
|
<label>
|
||||||
{{ page.title }}
|
{{ page.title }}
|
||||||
</label>
|
</label>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=rerre">
|
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfdff">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block mainContent %}
|
{% block mainContent %}
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
"homepage": "https://roiskinda.cool"
|
"homepage": "https://roiskinda.cool"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"brain\\":"brain"
|
||||||
|
}
|
||||||
|
},
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://code.playvicio.us/Are0h/Fipamo",
|
"source": "https://code.playvicio.us/Are0h/Fipamo",
|
||||||
"wiki": "https://code.playvicio.us/Are0h/Fipamo/wiki/_pages",
|
"wiki": "https://code.playvicio.us/Are0h/Fipamo/wiki/_pages",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "fipamo-default/frame.twig" %}
|
{% extends "frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
|
|
@ -1,31 +1,32 @@
|
||||||
/**
|
h1, h2, h3 {
|
||||||
-------------------------------
|
color: #ebe5d4;
|
||||||
-- Typography
|
}
|
||||||
-------------------------------
|
|
||||||
**/
|
h1 {
|
||||||
/**
|
font-size: 2em;
|
||||||
-------------------------------
|
font-weight: 400;
|
||||||
-- Colors
|
}
|
||||||
-------------------------------
|
|
||||||
**/
|
h2 {
|
||||||
/**
|
font-size: 1.75em;
|
||||||
-------------------------------
|
font-weight: 400;
|
||||||
-- Mixins
|
}
|
||||||
-------------------------------
|
|
||||||
**/
|
h3 {
|
||||||
/**
|
font-size: 1.5em;
|
||||||
-------------------------------
|
font-weight: 300;
|
||||||
-- Normalize
|
}
|
||||||
-------------------------------
|
|
||||||
**/
|
|
||||||
html {
|
html {
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
-ms-text-size-adjust: 100%;
|
-ms-text-size-adjust: 100%;
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
article,
|
article,
|
||||||
aside,
|
aside,
|
||||||
footer,
|
footer,
|
||||||
|
@ -34,62 +35,75 @@ nav,
|
||||||
section {
|
section {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
margin: 0.67em 0;
|
margin: 0.67em 0;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
figcaption,
|
figcaption,
|
||||||
figure,
|
figure,
|
||||||
main {
|
main {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
margin: 1em 40px;
|
margin: 1em 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
height: 0;
|
height: 0;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
font-family: monospace, monospace;
|
font-family: monospace, monospace;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
-webkit-text-decoration-skip: objects;
|
-webkit-text-decoration-skip: objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:active,
|
a:active,
|
||||||
a:hover {
|
a:hover {
|
||||||
outline-width: 0;
|
outline-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
abbr[title] {
|
abbr[title] {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-decoration: underline dotted;
|
text-decoration: underline dotted;
|
||||||
}
|
}
|
||||||
|
|
||||||
b,
|
b,
|
||||||
strong {
|
strong {
|
||||||
font-weight: inherit;
|
font-weight: inherit;
|
||||||
font-weight: bolder;
|
font-weight: bolder;
|
||||||
}
|
}
|
||||||
code,
|
|
||||||
kbd,
|
kbd,
|
||||||
samp {
|
samp {
|
||||||
font-family: monospace, monospace;
|
font-family: monospace, monospace;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
dfn {
|
dfn {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark {
|
mark {
|
||||||
background-color: #ff0;
|
background-color: #ff0;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub,
|
sub,
|
||||||
sup {
|
sup {
|
||||||
font-size: 60%;
|
font-size: 60%;
|
||||||
|
@ -97,31 +111,38 @@ sup {
|
||||||
position: relative;
|
position: relative;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub {
|
sub {
|
||||||
bottom: -0.25em;
|
bottom: -0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
sup {
|
sup {
|
||||||
top: -0.55em;
|
top: -0.55em;
|
||||||
background: #bdcbdb;
|
background: #151d26;
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0 2px 0 2px;
|
padding: 0 2px 0 2px;
|
||||||
margin: 0 2px 0 0;
|
margin: 0 2px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio,
|
audio,
|
||||||
video {
|
video {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio:not([controls]) {
|
audio:not([controls]) {
|
||||||
display: none;
|
display: none;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg:not(:root) {
|
svg:not(:root) {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
input,
|
input,
|
||||||
optgroup,
|
optgroup,
|
||||||
|
@ -132,38 +153,44 @@ textarea {
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
input {
|
input {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
select {
|
select {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
}
|
}
|
||||||
button,
|
|
||||||
html [type="button"],
|
button, html [type=button],
|
||||||
[type="reset"],
|
[type=reset],
|
||||||
[type="submit"] {
|
[type=submit] {
|
||||||
-webkit-appearance: button;
|
-webkit-appearance: button;
|
||||||
}
|
}
|
||||||
[type="button"]::-moz-focus-inner,
|
|
||||||
[type="reset"]::-moz-focus-inner,
|
[type=button]::-moz-focus-inner,
|
||||||
[type="submit"]::-moz-focus-inner,
|
[type=reset]::-moz-focus-inner,
|
||||||
|
[type=submit]::-moz-focus-inner,
|
||||||
button::-moz-focus-inner {
|
button::-moz-focus-inner {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
[type="button"]:-moz-focusring,
|
|
||||||
[type="reset"]:-moz-focusring,
|
[type=button]:-moz-focusring,
|
||||||
[type="submit"]:-moz-focusring,
|
[type=reset]:-moz-focusring,
|
||||||
|
[type=submit]:-moz-focusring,
|
||||||
button:-moz-focusring {
|
button:-moz-focusring {
|
||||||
outline: 1px dotted ButtonText;
|
outline: 1px dotted ButtonText;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
border: 1px solid #c0c0c0;
|
border: 1px solid #c0c0c0;
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
padding: 0.35em 0.625em 0.75em;
|
padding: 0.35em 0.625em 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
legend {
|
legend {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
@ -172,55 +199,143 @@ legend {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress {
|
progress {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
[type="checkbox"],
|
|
||||||
[type="radio"] {
|
[type=checkbox],
|
||||||
|
[type=radio] {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0;
|
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;
|
height: auto;
|
||||||
}
|
}
|
||||||
[type="search"] {
|
|
||||||
|
[type=search] {
|
||||||
-webkit-appearance: textfield;
|
-webkit-appearance: textfield;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
[type="search"]::-webkit-search-cancel-button,
|
|
||||||
[type="search"]::-webkit-search-decoration {
|
[type=search]::-webkit-search-cancel-button,
|
||||||
|
[type=search]::-webkit-search-decoration {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
::-webkit-file-upload-button {
|
||||||
-webkit-appearance: button;
|
-webkit-appearance: button;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
details,
|
details,
|
||||||
menu {
|
menu {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary {
|
summary {
|
||||||
display: list-item;
|
display: list-item;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
template {
|
template {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
[hidden] {
|
[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
-------------------------------
|
form {
|
||||||
-- Main Structure
|
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 {
|
html {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -229,6 +344,7 @@ html {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font: 400 1.2em/1.4em Helvetica, Arial, sans-serif;
|
font: 400 1.2em/1.4em Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: #ebe5d4;
|
background: #ebe5d4;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -240,51 +356,79 @@ body {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: 1px solid #7ed07e;
|
border-bottom: 1px solid #7ED07E;
|
||||||
-moz-transition: all 0.2s linear;
|
|
||||||
-webkit-transition: all 0.2s linear;
|
|
||||||
-o-transition: all 0.2s linear;
|
|
||||||
transition: all 0.2s linear;
|
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
border-bottom: 1px solid #fc6399;
|
border-bottom: 1px solid #FC6399;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
background: #32302f;
|
background: #32302f;
|
||||||
color: #7ed07e;
|
color: #7ED07E;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #32302f;
|
background: #32302f;
|
||||||
color: #7ed07e;
|
color: #7ED07E;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
pre code {
|
|
||||||
color: #fc6399;
|
code {
|
||||||
|
color: #FC6399;
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg.icons {
|
svg.icons {
|
||||||
width: 25px;
|
width: 25px;
|
||||||
fill: #ebe5d4;
|
fill: #ebe5d4;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
background: #151d26;
|
background: #151d26;
|
||||||
height: 90%;
|
height: 90%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-top: #ebe5d4 3px solid;
|
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 {
|
header nav {
|
||||||
width: 97%;
|
width: 97%;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
|
z-index: 1000;
|
||||||
|
position: relative;
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
}
|
}
|
||||||
header nav .left,
|
header nav .left, header nav .right {
|
||||||
header nav .right {
|
|
||||||
width: 50%;
|
width: 50%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
@ -302,7 +446,7 @@ header nav .right {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
header nav .right a.menu-link {
|
header nav .right a.menu-link {
|
||||||
background: #fc6399;
|
background: #FC6399;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
@ -311,8 +455,9 @@ header nav .right a.menu-link {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
header nav .right a.menu-link:hover {
|
header nav .right a.menu-link:hover {
|
||||||
background: #feb1cc;
|
background: #FC6399;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
background: #ebe5d4;
|
background: #ebe5d4;
|
||||||
|
@ -331,57 +476,47 @@ header nav .right a.menu-link:hover {
|
||||||
color: #32302f;
|
color: #32302f;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.container article .index,
|
.container article .index, .container article .page {
|
||||||
.container article .page {
|
|
||||||
padding: 0 0 15px 0;
|
padding: 0 0 15px 0;
|
||||||
}
|
}
|
||||||
.container article .index img,
|
.container article .index img, .container article .page img {
|
||||||
.container article .page img {
|
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.container article .index h1,
|
.container article .index h1, .container article .page h1 {
|
||||||
.container article .page h1 {
|
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
}
|
}
|
||||||
.container article .index p,
|
.container article .index p, .container article .page p {
|
||||||
.container article .page p {
|
|
||||||
font: 300 1.25em/1.6em Helvetica, Arial, sans-serif;
|
font: 300 1.25em/1.6em Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
.container article .index .meta,
|
.container article .index .meta, .container article .page .meta {
|
||||||
.container article .page .meta {
|
|
||||||
font: 500 0.8em/1.3em Helvetica, Arial, sans-serif;
|
font: 500 0.8em/1.3em Helvetica, Arial, sans-serif;
|
||||||
padding: 5px 0 0 0;
|
padding: 5px 0 0 0;
|
||||||
border-top: 1px solid #151d26;
|
border-top: 1px solid #151d26;
|
||||||
background: #ede8d8;
|
background: #ebe5d4;
|
||||||
}
|
}
|
||||||
.container article .index .meta a,
|
.container article .index .meta a, .container article .page .meta a {
|
||||||
.container article .page .meta a {
|
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
.container article .index .archive-item,
|
.container article .index .archive-item, .container article .page .archive-item {
|
||||||
.container article .page .archive-item {
|
|
||||||
padding: 15px 0 20px 0;
|
padding: 15px 0 20px 0;
|
||||||
}
|
}
|
||||||
.container article .index .archive-item span.year,
|
.container article .index .archive-item span.year, .container article .page .archive-item span.year {
|
||||||
.container article .page .archive-item span.year {
|
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
display: block;
|
display: block;
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
}
|
}
|
||||||
.container article .index .archive-item .archive-month,
|
.container article .index .archive-item .archive-month, .container article .page .archive-item .archive-month {
|
||||||
.container article .page .archive-item .archive-month {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
width: 30%;
|
width: 30%;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
.container article .index .archive-item .archive-month span.month,
|
.container article .index .archive-item .archive-month span.month, .container article .page .archive-item .archive-month span.month {
|
||||||
.container article .page .archive-item .archive-month span.month {
|
color: #FC6399;
|
||||||
color: #fc6399;
|
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
@ -394,35 +529,31 @@ header nav .right a.menu-link:hover {
|
||||||
.container section a {
|
.container section a {
|
||||||
color: #ebe5d4;
|
color: #ebe5d4;
|
||||||
}
|
}
|
||||||
.container section .index-lists,
|
.container section .index-lists, .container section .page-title {
|
||||||
.container section .page-title {
|
|
||||||
max-width: 840px;
|
max-width: 840px;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px 0 0 0;
|
padding: 20px 0 0 0;
|
||||||
}
|
}
|
||||||
.container section .index-lists span,
|
.container section .index-lists span, .container section .page-title span {
|
||||||
.container section .page-title span {
|
font-size: 2em;
|
||||||
font: 600 2em/1.5 Helvetica, Arial, sans-serif;
|
color: #FC6399;
|
||||||
color: #ebe5d4;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
.container section .index-lists .recent,
|
.container section .index-lists .recent, .container section .index-lists .featured, .container section .page-title .recent, .container section .page-title .featured {
|
||||||
.container section .page-title .recent,
|
|
||||||
.container section .index-lists .featured,
|
|
||||||
.container section .page-title .featured {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
.container section .index-lists label,
|
.container section .index-lists label, .container section .page-title label {
|
||||||
.container section .page-title label {
|
|
||||||
background: #32302f;
|
background: #32302f;
|
||||||
color: #ebe5d4;
|
color: #ebe5d4;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
background: #e4dcc5;
|
background: #ebe5d4;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #151d26;
|
color: #151d26;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
|
@ -435,121 +566,44 @@ footer .inner {
|
||||||
max-width: 840px;
|
max-width: 840px;
|
||||||
}
|
}
|
||||||
footer .inner a {
|
footer .inner a {
|
||||||
color: #fc6399;
|
color: #FC6399;
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 640px) {
|
|
||||||
header nav {
|
header nav {
|
||||||
width: 98%;
|
width: 98%;
|
||||||
}
|
|
||||||
header span {
|
|
||||||
font-size: 2.5em;
|
|
||||||
}
|
|
||||||
.container article .index .archive-item .archive-month,
|
|
||||||
.container article .page .archive-item .archive-month {
|
|
||||||
width: 45%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 480px) {
|
header span {
|
||||||
header nav {
|
font-size: 2.5em;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 375px) {
|
header .container article .index .archive-item .archive-month, header .container article .page .archive-item .archive-month {
|
||||||
header nav {
|
width: 45%;
|
||||||
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 nav {
|
||||||
-- Forms
|
width: 96%;
|
||||||
-------------------------------
|
|
||||||
**/
|
|
||||||
form {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
input[type=email],
|
header .container article .index, header .container article .page {
|
||||||
input[type=password],
|
margin: 0;
|
||||||
input[type=text] {
|
|
||||||
border: 0;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
margin: 10px 5px 0 0;
|
|
||||||
font: 15px 'RobotoMono';
|
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
textarea {
|
header .container article .index p, header .container article .page p {
|
||||||
border: 0;
|
font: 300 1em/1.6em Helvetica, Arial, sans-serif;
|
||||||
border-radius: 3px;
|
|
||||||
color: $type02;
|
|
||||||
font: 15px 'RobotoMono';
|
|
||||||
}
|
}
|
||||||
button,
|
header .container section .index-lists .recent, header .container section .index-lists .featured {
|
||||||
input[type=submit] {
|
width: 100% !important;
|
||||||
background: #fc6399;
|
|
||||||
color: #ebe5d4;
|
|
||||||
font: 14px Helvetica, Arial, sans-serif;
|
|
||||||
border-radius: 5px;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 0;
|
|
||||||
padding: 5px 5px 0 5px;
|
|
||||||
-moz-transition: all 0.3s linear;
|
|
||||||
-webkit-transition: all 0.3s linear;
|
|
||||||
-o-transition: all 0.3s linear;
|
|
||||||
transition: all 0.3s linear;
|
|
||||||
}
|
}
|
||||||
button:hover,
|
|
||||||
input[type=submit]:hover {
|
header nav {
|
||||||
background: #fc7ca9;
|
width: 95%;
|
||||||
}
|
}
|
||||||
select {
|
|
||||||
font: 14px 'RobotoMono';
|
.container article .index, .container article .page {
|
||||||
border: 1px solid #fc6399;
|
margin: 0;
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
color: #151d26;
|
|
||||||
}
|
}
|
||||||
::-webkit-input-placeholder {
|
.container article .index p, .container article .page p {
|
||||||
font: 14px 'RobotoMono';
|
font: 300 0.9em/1.7em Helvetica, Arial, sans-serif;
|
||||||
color: #837e7c;
|
|
||||||
}
|
}
|
||||||
:-moz-placeholder {
|
.container article .index .archive-item .archive-month, .container article .page .archive-item .archive-month {
|
||||||
/* Firefox 18- */
|
width: 95%;
|
||||||
font: 14px 'RobotoMono';
|
|
||||||
color: #837e7c;
|
|
||||||
}
|
}
|
||||||
::-moz-placeholder {
|
|
||||||
/* Firefox 19+ */
|
/*# sourceMappingURL=base.css.map */
|
||||||
font: 14px 'RobotoMono';
|
|
||||||
color: #837e7c;
|
|
||||||
}
|
|
||||||
:-ms-input-placeholder {
|
|
||||||
font: 14px 'RobotoMono';
|
|
||||||
color: #837e7c;
|
|
||||||
}
|
|
||||||
/*# 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>
|
<!DOCTYPE html>
|
||||||
|
|
||||||
{% if debug is defined %}
|
{% if debug is defined %}
|
||||||
{% set assetPath = '/src/themes/theme-fipamo-default/fipamo-default/assets/' %}
|
{% set assetPath = '/src/themes/theme-'~theme~'/'~theme~'/assets/' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set assetPath = '/assets/' %}
|
{% set assetPath = '/assets/' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -15,15 +15,52 @@
|
||||||
</title>
|
</title>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
<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 name="description" content="{{info['description']}} " />
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
<meta property="og:image" content="{{info["image"]}}" />
|
<meta property="og:image" content="{{info["image"]}}" />
|
||||||
<meta name="twitter:image" content="{{info["image"]}}" />
|
<meta name="twitter:image" content="{{info["image"]}}" />
|
||||||
<link rel="stylesheet" type="text/css" href="{{ assetPath~"css/base.css?=adfafd" }}">
|
<link rel="stylesheet" type="text/css" href="{{ assetPath~"css/base.css?=dfvbghh" }}">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!--
|
||||||
<header style="background: url({{ background }}) no-repeat center center; background-size: cover">
|
<header style="background: url({{ background }}) no-repeat center center; background-size: cover">
|
||||||
|
-->
|
||||||
|
<header>
|
||||||
|
<div id="media">
|
||||||
|
{% if media|length > 1 %}
|
||||||
|
{% for item in media %}
|
||||||
|
{% if item.type == "mp4"%}
|
||||||
|
<div id="{{loop.index0}}" class="slide">
|
||||||
|
<video controls autoplay muted>
|
||||||
|
|
||||||
|
<source src="{{item.file}}" type="video/mp4">
|
||||||
|
|
||||||
|
Please get a better browser. They're free.
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div id="{{loop.index0}}" class="slide hide" style="background: url({{ item.file }}) no-repeat center center / cover"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
{% if media[0] != '' %}
|
||||||
|
{% if media[0].type == "mp4"%}
|
||||||
|
<div id="0" class="slide">
|
||||||
|
<video controls autoplay muted>
|
||||||
|
|
||||||
|
<source src="{{media[0].file}}" type="video/mp4">
|
||||||
|
|
||||||
|
Please get a better browser. They're free.
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div id="0" class="slide" style="background: url({{ media[0].file }}) no-repeat center center / cover"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
{% apply spaceless %}
|
{% apply spaceless %}
|
||||||
<div class="left">
|
<div class="left">
|
||||||
|
@ -43,7 +80,6 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
|
<a href="{{"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -68,10 +104,9 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="/archives.html">Archives</a><br />
|
<a href="/archives.html">Archives</a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
© 2020 By Fipamo
|
© 2020 By Fipamo
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<script src="{{ assetPath~"scripts/start.min.js" }}" type="text/javascript"></script>
|
<script src="{{ assetPath~"scripts/ThemeStart.js" }}" type="text/javascript"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "fipamo-default/frame.twig" %}
|
{% extends "frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "fipamo-default/frame.twig" %}
|
{% extends "frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
</section>
|
</section>
|
||||||
<article>
|
<article>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
THIS IS A CUSTOM TEMPLATE <br />
|
[CUSTOM PAGE BRUH]
|
||||||
<p>{{content | raw}}</p>
|
<p>{{content | raw}}</p>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
<strong>tags: </strong>
|
<strong>tags: </strong>
|
||||||
{% for tag in meta['tags'] %}
|
{% for tag in meta['tags'] %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'true' %}
|
{% if dynamicRender == 'false' %}
|
||||||
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
|
@ -28,7 +28,6 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "fipamo-default/frame.twig" %}
|
{% extends "frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<strong>tags: </strong>
|
<strong>tags: </strong>
|
||||||
{% for tag in meta['tags'] %}
|
{% for tag in meta['tags'] %}
|
||||||
{% if dynamicRender is defined %}
|
{% if dynamicRender is defined %}
|
||||||
{% if dynamicRender == 'false' %}
|
{% if dynamicRender == 'true' %}
|
||||||
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
|
@ -27,7 +27,6 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "fipamo-default/frame.twig" %}
|
{% extends "frame.twig" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -23,7 +23,6 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
|
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2290,6 +2290,8 @@ svg.icons {
|
||||||
}
|
}
|
||||||
#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 {
|
#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%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
position: absolute;
|
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 {
|
#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 {
|
||||||
|
|
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 |
File diff suppressed because it is too large
Load diff
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
|
<?php
|
||||||
|
|
||||||
require "../vendor/autoload.php";
|
require "../vendor/autoload.php";
|
||||||
include "../brain/App.inc.php";
|
|
||||||
|
use brain\init\App as App;
|
||||||
|
|
||||||
new App();
|
new App();
|
||||||
|
|
|
@ -158,6 +158,8 @@
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
.post-video
|
.post-video
|
||||||
width: 100%
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
object-fit: cover
|
||||||
position: absolute
|
position: absolute
|
||||||
|
|
||||||
label
|
label
|
||||||
|
|
Loading…
Reference in a new issue