This commit is contained in:
Florian Bouillon 2019-03-02 15:54:10 +01:00
parent bc8fba19d4
commit 17f223d517
32 changed files with 366 additions and 288 deletions

3
.gitignore vendored
View File

@ -1,2 +1,5 @@
.vscode/
cache/
/vendor/
composer.lock

1
.phpunit.result.cache Normal file
View File

@ -0,0 +1 @@
C:30:"PHPUnit\Runner\TestResultCache":204:{a:2:{s:7:"defects";a:1:{s:29:"TestEnum::testInstantiateEnum";i:3;}s:5:"times";a:3:{s:25:"TestEnum::testValidOption";d:0;s:25:"TestEnum::testIsValidName";d:0;s:29:"TestEnum::testInstantiateEnum";d:0.003;}}}

View File

View File

View File

View File

@ -1,5 +0,0 @@
<?php
function headGenerator() {
return "<title>Title</title>";
}

View File

@ -1 +0,0 @@
{"Page":{"URI":"templates\/page.php","function":"page","static":true}}

View File

@ -1,13 +0,0 @@
<?php
function page() {
// require_once "includes/header.php";
// echo PAGE["content"];
// require_once "includes/footer.php";
return "<header>Header</header>" . PAGE["content"] . "<footer>Footer</footer>";
}
?>

20
composer.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "avior/admin-panel",
"type": "project",
"license": "MIT License",
"authors": [
{
"name": "Avior",
"email": "florian.bouillon@delta-wings.net"
}
],
"autoload": {
"classmap": [
"src/admin/system/"
]
},
"require": {},
"require-dev": {
"phpunit/phpunit": "^8"
}
}

View File

@ -1,9 +0,0 @@
{
"title": "Home",
"template": "Page",
"access": "public",
"content": "<main>Hello World</main>",
"modules": {
"?": "?"
}
}

View File

@ -1,3 +0,0 @@
{
"title":"test"
}

View File

@ -1,40 +0,0 @@
<?php
/**
* The process to load a public page (located in /pages)
*/
$isCacheActive = SETTINGS["cache"];
$webPage = "<html><head><placeholder type=\"head\"/></head><body>" . getWebPage($isCacheActive) . "</body>";
//load .css & .js
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($webPage);
libxml_clear_errors();
//handle modules here
echo $doc->saveHTML();
/*
if cache is active
if active is active load cache (scripts.js styles.css)
load templates.json
if template has cache for webpage and cache exist
load the file
else
launch generateWebPage()
load theme css & js
if modules are in the page
load the modules
*/
?>

249
readme.md
View File

@ -6,19 +6,17 @@
- [Table of Content](#table-of-content)
- [Description](#description)
- [Changelog](#changelog)
- [Themes](#themes)
- [Templates](#templates)
- [styles & scripts](#styles--scripts)
- [Options](#options)
- [Modules](#modules)
- [Routes](#routes)
- [Usage](#usage)
- [Menus](#menus)
- [Usage](#usage-1)
- [Options](#options)
- [Usage](#usage-2)
- [Files/Folders architecture](#filesfolders-architecture)
- [Configs files](#configs-files)
- [page.json (in `pages` folder)](#pagejson-in-pages-folder)
- [scripts.json & styles.json](#scriptsjson--stylesjson)
- [admin.json](#adminjson)
- [vars.json](#varsjson)
- [moduleName.json & themeName.json](#modulenamejson--themenamejson)
- [templates.json](#templatesjson)
- [site.json](#sitejson)
- [settings.json](#settingsjson)
## Description
@ -28,127 +26,113 @@ WIP
see [changelog.md](./changelog.md)
## Themes
## Modules
### Templates
themes works via "templates".
first a template named "page" is a must, your template can be static or not (static templates will be updated on document update while not static the templateFile will always be used)
Modules are what that will manage the system in himself.
```php
website->addTemplate("Template Name", "templateURI/from/root/page.php", "functionName", true);
$module = new Module();
```
- `"Template Name"` is the shown name
- `"templateURI"` is the file URI
- `"functionName"` is the function used
- `true` is to says to the website if this template is static or not (default to `false`)
Modules will have multiple constant
if cache is disabled globally static or not static pages will be updated at every load
### Routes
example: a template named `Blog Page` can be static while a `Blog List` shouldn't be static to load newly added blog pages
sitewide (except `/admin/*`) routes can be defined and will point to a function you will have to define
#### Usage
```php
website->addTemplate("Blog Page", "templates/blog.php", "page", true);
website->addTemplate("Blog List", "templates/blog.php", "list", false);
$function = function($settings) {
return "html code";
}
$module->addRoute("/regex-to-check-for-the-page/", $function);
```
### styles & scripts
### Menus
themes must declare each scripts & styles so they can be cached when needed
On the admin-side you can add menus & items
#### Usage
```php
website->addNewStyle("styleURI/from/style/root/page.css", "styleName", ["styleDependency"]);
website->addNewScript("scriptURI/from/script/root/page.js", "scriptName", ["scriptdependency", "JQuery"]);
$menu = $module->addMenu("Menu Name");
$pageFunction = function($settings) {
return "html code"; //not <html> nor <body>
}
$menu->addItem("Item Name", $pageFunction);
```
- `"styleURI"`/`"scriptURI"` is the link to the file
- [OPTIONAL] `"styleName"`/`"scriptName"` is the name of the style/script to be used by sub-dependencies
- [OPTIONAL] `["styleDependency"]`/`["scriptDependency", "JQuery"]` are used to load theses scripts after the followed dependencies
### Options
Options are declarated in the same file than before
and will be usable in the templates files
updating an option will update the static files
#### Usage
```php
$optionMenu = website->addOptionsMenu("Menu Name");
```
$options = $module->addOptionItem("Item Name");
here we create a new option menu that will be located in the admin sidebar `theme -> Options` within the tabs
- `"Menu Name"` is the shown name
```php
$optionMenu->addTextOption("Option Name", "variableName", "defaultValue", {
"min": 1,
"max": 16,
"placeholder": "placeholder"
$options->addOption("Option Name", "optionName", OptionTypes::text)
$options->addOption("optionVar", OptionTypes::Text, {
"name": "Name",
"placeholder": "placeholder",
"default": "defaultValue"
// more options will come later
});
```
## Modules
```js
/*
possibilité de mettre des routes qui executent des functions
ajouter des pages dans la section d'admin
(Module) to initialize & manage the module
(Menu, Item from Menu) classes to manage adminPanel elements
(Variables) class to get/set used around the website vars
(OptionsItem from Item) to have a custom page for settings
(OptionsTab, Option)
modules will work like this in the `page.content` of the page `[moduleName variablesName="valueName"]`
*/
$module = new Module();
the module will then receive a variable named `$modVars` that will contain `$modVars->variableName` = `valueName` and will have to return a `String` Object
$menu = $module.addMenu("menuName");
$menu.addItem("itemName", function());
To keep the document strict it's advised to use the php `DOMDocument` Object
options = Module.addOptionsMenu("name");
optionTab = options.addOptionTab("name");
optionTab.addOption("test", =enum.text);
//options added will be in the first tab named at the menu name
//if there is only one tab or no tab we won't show tabs
options.addOption("test", =enum.text);
//add options if it is equal to something
//true/false is what it must be to be shown
//with be in js i think
options.addOption("option name"=String, enum.text=enumeType, "option to check", "regex to check with", must it true or false)
```
## Files/Folders architecture
- index.php (is it really necessary ?)
- .htaccess (handle file redirection)
- router.php (handle the first route part ( separating the loading process))
- uploads/
- cache/ (public cache (won't be seen by client via .htaccess redirection))
- .htaccess (make sure clients can't access this folder)
- scripts.js
- styles.css
- pages/ (NO `scripts.js` NOR `styles.css` NOR `admin` NOR `login` files must be in here)
- .htaccess (make sure clients can't access this folder)
- index.json (this index.json will be the root name "/")
- slugname.json (path = "/slugname")
- iamjson.json.json (path = "/iamjson.json" wand with a module/theme could just return json)
- folderslug/
- index.json (path = "/folderslug" if no index.json is given there will be a 404 error for "/folderslug" but not for the "/folderslug/pouet")
- pouet.json (path = "/folderslug/pouet")
- admin/
- .htaccess manage redirection for admin pages (pass throught a verify login script)
- index.php
- admin.js
- admin.css
- settings/ (settings files more infos [here](#config-files))
- scripts.json (if cache is disabled these files will be used to get the styles & scripts)
- styles.json (else these files are only used to create the caches files)
- admin.json (admin settings (see admin.json section))
- templates.json (simple name to redirect)
- site.json (adminPanel settings (see admin.json section))
- modules/
- moduleName/
- settings.json
- vars.json
- themes/
- themeName/
- settings.json
- vars.json
- admin.json (used to see what to launch on the admin side)
- options.json (options for modules & themes to be used site-wide)
- templates.json (store the template used on the website with a link to there .php file)
- themes/ (when a new theme is loaded regenerate scripts.js & styles.css, an option will allow the use of direct files)
- default/ (a default theme will be here)
- theme.php
- themeName/
- theme.php (only launched on theme load, to generate cache files & admin options files)
- public.php (launched everytime on website when page is launched (admins sections are excluded)
- admin.php (launched everytime on admin/themename/** launch (with args like page))
- templates/ (all folders included under are optional anc can be located somewhere else in the theme folder)
- page.php (at least a template named "page" must exist to make the theme usable)
- templateName.php (file launched everytime a page is loaded with the template selected)
- css/
- js/
- modules/
- default/ (a default module will be here)
- module.php
@ -159,29 +143,11 @@ To keep the document strict it's advised to use the php `DOMDocument` Object
## Configs files
### page.json (in `pages` folder)
### site.json
```json
{
"title": "pageTitle",
"template": "templateName",
"access": "typeOfAccess (public: everyone has access to the page, limited:only logged in users has access to the page, private: only the author & admins has access to the page)",
"author": "Aviortheking",
"content": "<h1>hello world</h1>"
}
```
Site-wide settings (don't know if it will be accesible for modules)
### scripts.json & styles.json
```json
{
[
"path/to/script"
]
}
```
### admin.json
Location: `/admin/settings/`
```json
{
@ -193,7 +159,11 @@ To keep the document strict it's advised to use the php `DOMDocument` Object
}
```
### vars.json
### settings.json
Stock the module variables
Location: `/admin/settings/modules/moduleName/`
```json
{
@ -207,64 +177,3 @@ To keep the document strict it's advised to use the php `DOMDocument` Object
}
}
```
### moduleName.json & themeName.json
values for the options are located in the `vars.json` files
```json
{
[
{
"title": "Menu Title",
"slug": "menu-title",
"options": {
"textOption": {
"type": "text",
"name": "Option Name",
},
"radioOption": {
"type": "radio",
"name": "Radio Option",
"values": [
"value1",
"value2",
"value3"
],
},
"selectOption": {
"type": "select",
"name": "Select",
"value": [
"value1",
"value2",
"value3",
"etc"
]
}
}
},
{
"title": "etc"
}
]
}
```
### templates.json
liste des tempplates crée par le theme
*voir si il y auras tout les themes ou seulement le theme actif*
if static is true then static webpage will be generated
```json
{
"templateName": {
"URI": "templates/templateName.php",
"function": "functionName",
"static": false
}
}
```

View File

@ -1,46 +0,0 @@
<?php
/**
* this file initialize some variables and do the first part of the routing (between public pages & admin pages)
*/
require_once "admin/system/functions.php";
ini_set('display_errors', 'On');
$url = strtolower(endsWith($_SERVER["REQUEST_URI"], "/") ? $_SERVER["REQUEST_URI"] . "index" : $_SERVER["REQUEST_URI"]);
define("URL", $url);
define("ROOT", __DIR__);
define("SETTINGS", loadJSON(ROOT . "/admin/settings/admin.json"));
// $website = new Website();
// var_dump(__DIR__);
$_SERVER = null;
if($url == "/test") {
require_once "test.php";
die;
}
$fileURI = "./pages" . $url . ".json";
if(in_array(explode("/", $url)[1], ["login", "admin"])) echo ("this is the login/admin page");
elseif (file_exists($fileURI)) {
require_once "public/public.php";
} else echo "404";
/*
verify if the page to load exist
if page is login/admin then continue;
elif the page is a file in /pages/pagename.json then continue
else return 404 error
verify if user is logged in
if the user is logged in & the page is login return to /admin
elif the user is not logged in & the page is admin return to /login
else start the process to load the page
*/
?>

View File

@ -1,4 +1,4 @@
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ ./router.php [L,QSA]
RewriteRule ^(.*)$ ./admin/init.php [L,QSA]

8
src/admin/init.php Normal file
View File

@ -0,0 +1,8 @@
<?php
ini_set('display_errors', 'On');
define("ROOT", __DIR__);
// require_once ROOT . "/system/router.php";
// define("ROUTER", Router::getRouter());

View File

@ -0,0 +1,3 @@
<?php
//page where you edit a frontend page in the adminPanel

View File

@ -0,0 +1 @@
<?php

45
src/admin/system/Enum.php Normal file
View File

@ -0,0 +1,45 @@
<?php
//
abstract class Enum {
private static $constCacheArray = NULL;
private static function getConstants() {
if (self::$constCacheArray == NULL) {
self::$constCacheArray = [];
}
$calledClass = get_called_class();
if (!array_key_exists($calledClass, self::$constCacheArray)) {
$reflect = new ReflectionClass($calledClass);
self::$constCacheArray[$calledClass] = $reflect->getConstants();
}
return self::$constCacheArray[$calledClass];
}
public static function isValidName($name, $strict = false) {
$constants = self::getConstants();
if ($strict) {
return array_key_exists($name, $constants);
}
$keys = array_map('strtolower', array_keys($constants));
return in_array(strtolower($name), $keys);
}
public static function isValidValue($value, $strict = true) {
$values = array_values(self::getConstants());
return in_array($value, $values, $strict);
}
}
// abstract class DaysOfWeek extends BasicEnum {
// const Sunday = 0;
// const Monday = 1;
// const Tuesday = 2;
// const Wednesday = 3;
// const Thursday = 4;
// const Friday = 5;
// const Saturday = 6;
// }

View File

@ -0,0 +1,6 @@
<?php
class OptionTypes extends Enum {
const String = 0;
const Integer = 1;
}

View File

@ -0,0 +1,35 @@
<?php
class Router {
private static $instance;
private $routeList = [];
private function __construct() {}
public static function getInstance() {
if($instance !== null) {
Router::$instance = new Self();
}
return Router::$instance;
}
public function addRoute(string $regex, $function) {
$this->routeList[$regex] = $function;
}
public function search(String $route) {
foreach ($this->routeList as $key => $value) {
if(preg_match($key, $route)) {
return $value;
}
}
return null;
}
}

View File

@ -0,0 +1,75 @@
<?php
/*
possibilité de mettre des routes qui executent des functions
ajouter des pages dans la section d'admin
(Module) to initialize & manage the module
(Menu, Item from Menu) classes to manage adminPanel elements
(Variables) class to get/set used around the website vars
(OptionsItem from Item) to have a custom page for settings
(OptionsTab, Option)
*/
/*
menu = Module.addMenu("menuName");
menu.addItem("itemName", function());
options = Module.addOptionsMenu("name");
optionTab = options.addOptionTab("name");
optionTab.addOption("test", =enum.text);
//options added will be in the first tab named at the menu name
//if there is only one tab or no tab we won't show tabs
options.addOption("test", =enum.text);
//add options if it is equal to something
//true/false is what it must be to be shown
//with be in js i think
options.addOption("option name"=String, enum.text=enumeType, "option to check", "regex to check with", must it true or false)
*/
class Menu {
private $items = array();
public function __construct() {
}
public function addMenu(Menu $menu) {
array_push($this->items, $menu);
}
public function addItem(Item $item) {
array_push($this->items, $item);
}
}
class Item {
private $name;
private $url;
private $function;
public function toLoad($function) {
$this->function = $function;
}
}
class OptionItem extends Item {
/*
*/
}
abstract class Module {
}

View File

@ -0,0 +1,55 @@
<?php
/**
* classe pour gerer le routage des pages
* la variable static $router sert a utiliser le router dans plusieurs fichier
* sans forcement avoir une obligation de nom de variable
* de plus ils sert a garder une route unique
*/
class Router {
//variable static pour stocker le router
private static $router = null;
//definit le router
public function __construct() {
if(Router::$router != null) {
return Router::$router;
} else Router::$router = $this;
}
//fonction static pour recuperer un router déjà crée
public static function getRouter() {
if(Router::$router == null) {
Router::$router = new Router();
}
return Router::$router;
}
//liste des routes
private $routeList = array();
//ajout d'une route
public function addRoute($route, $page) {
$this->routeList[$route] = $page;
}
//fonction de recherche d'une route par rapport a un texte
//return function
public function search($path) {
foreach ($this->routeList as $reg => $page) {
if(preg_match($reg, $path)) {
return $page;
}
}
return function () {
return "404";
};
}
public function redirecter($source, $redirectPage) {
$this->addRoute($source, function() {
header("Location: " . $redirectPage);
});
}
}

34
tests/TestEnum.php Normal file
View File

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class TestEnum extends TestCase {
public function testInstantiateEnum(): void {
$this->expectException(Error::class);
new Enum();
}
public function testValidOption(): void {
$this->assertEquals(
0,
OptionTypes::String
);
}
public function testIsValidName(): void {
$this->assertEquals(
true,
OptionTypes::isValidName("String")
);
$this->assertEquals(
false,
OptionTypes::isValidName("Sting")
);
$this->assertEquals(
false,
OptionTypes::isValidName("string", true)
);
}
}