All changes as implemented over the last 3 years.
Pushes Administration into a workable state.
This commit is contained in:
parent
50608c18e7
commit
63ea659d5b
6
Dockerfile
Normal file → Executable file
6
Dockerfile
Normal file → Executable file
@ -1,10 +1,6 @@
|
||||
FROM php:7.3-apache
|
||||
FROM registry.i15.nl/i15/fuzephp:8.1-apache
|
||||
MAINTAINER i15 <abel@i15.nl>
|
||||
|
||||
# Install PHP Deps
|
||||
# First PDO and MySQL
|
||||
RUN docker-php-ext-install mysqli pdo_mysql opcache
|
||||
|
||||
# Write application to image
|
||||
ENV APACHE_DOCUMENT_ROOT /usr/src/admin/www
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
|
||||
|
2
LICENSE
Normal file → Executable file
2
LICENSE
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-2020 i15
|
||||
Copyright (c) 2013-2023 i15
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
22
composer.json
Normal file → Executable file
22
composer.json
Normal file → Executable file
@ -1,7 +1,6 @@
|
||||
{
|
||||
"name": "fuzeworks/administration",
|
||||
"description": "description",
|
||||
"minimum-stability": "stable",
|
||||
"description": "Administration interface for FuzeWorks",
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
@ -10,19 +9,16 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"fuzeworks/core": "~1.2",
|
||||
"fuzeworks/mvcr": "~1.2",
|
||||
"fuzeworks/webcomponent": "~1.2",
|
||||
"fuzeworks/layout": "~1.2",
|
||||
"fuzeworks/database": "~1.2",
|
||||
"latte/latte": "^2",
|
||||
"almasaeed2010/adminlte": "^3",
|
||||
"phpdocumentor/reflection-docblock": "^5"
|
||||
"php": ">=8.1.0",
|
||||
"fuzeworks/webcomponent": "~1.3.0",
|
||||
"fuzeworks/authentication": "~1.3.0",
|
||||
"fuzeworks/layout": "~1.3.0",
|
||||
"latte/latte": "~2.5",
|
||||
"almasaeed2010/adminlte": "^3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9",
|
||||
"fuzeworks/tracycomponent": "~1.2"
|
||||
"fuzeworks/tracycomponent": "~1.3.0",
|
||||
"phpunit/phpunit": "^9"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
0
config.admin.php
Normal file → Executable file
0
config.admin.php
Normal file → Executable file
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks Framework Administration Plugin.
|
||||
* i15Site.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2020 i15
|
||||
* Copyright (C) 2013-2022 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -25,18 +25,18 @@
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2020, i15. (https://i15.nl)
|
||||
* @copyright Copyright (c) 2013 - 2022, i15. (http://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.3.0
|
||||
* @link https://i15.nl
|
||||
* @since Version 2.0.0
|
||||
*
|
||||
* @version Version 1.3.0
|
||||
* @version Version 2.0.0
|
||||
*/
|
||||
|
||||
namespace Application\Controller;
|
||||
use FuzeWorks\WebController;
|
||||
|
||||
class IndexController extends WebController
|
||||
class AsyncController extends WebController
|
||||
{
|
||||
|
||||
}
|
36
controllers/main/controller.cache.php
Normal file
36
controllers/main/controller.cache.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Application\Controller;
|
||||
|
||||
use FuzeWorks\Factory;
|
||||
use FuzeWorks\ObjectStorage\ObjectStorageComponent;
|
||||
use FuzeWorks\WebController;
|
||||
|
||||
class CacheController extends WebController
|
||||
{
|
||||
|
||||
public function getCacheItems(int $index = 1, int $pageSize = 50): ?array
|
||||
{
|
||||
// Get storage
|
||||
/** @var ObjectStorageComponent $storage */
|
||||
$storage = Factory::getInstance("storage");
|
||||
$store = $storage->getStorage();
|
||||
|
||||
// First retrieve the index
|
||||
$objectIndex = $store->getIndex();
|
||||
|
||||
$out = [];
|
||||
for ($i = $index; $i < ($index + $pageSize); $i++)
|
||||
{
|
||||
if (!isset($objectIndex[$i]))
|
||||
continue;
|
||||
|
||||
|
||||
$out[] = $store->getItem($objectIndex[$i]);
|
||||
//$out[] = $store->getItemMeta($objectIndex[$i]);
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
21
views/view.admin.index.php → controllers/main/controller.dashboard.php
Normal file → Executable file
21
views/view.admin.index.php → controllers/main/controller.dashboard.php
Normal file → Executable file
@ -33,23 +33,18 @@
|
||||
* @version Version 1.3.0
|
||||
*/
|
||||
|
||||
namespace Application\View;
|
||||
use FuzeWorks\Administration\AdminView;
|
||||
namespace Application\Controller;
|
||||
use FuzeWorks\Administration\Attributes\DashboardAttribute;
|
||||
use FuzeWorks\Administration\PageFinder;
|
||||
use FuzeWorks\WebController;
|
||||
|
||||
class IndexAdminView extends AdminView
|
||||
class DashboardController extends WebController
|
||||
{
|
||||
|
||||
/**
|
||||
* Hello!
|
||||
*
|
||||
* This does a lot of things
|
||||
*
|
||||
* @display Dashboard
|
||||
* @icon tachometer-alt
|
||||
* @priority Priority::HIGHEST
|
||||
*/
|
||||
public function index()
|
||||
public function populateDashboard()
|
||||
{
|
||||
$finder = new PageFinder();
|
||||
$views = $finder->findViewsWithAttribute(DashboardAttribute::class);
|
||||
}
|
||||
|
||||
}
|
74
controllers/controller.settings.php → controllers/main/controller.settings.php
Normal file → Executable file
74
controllers/controller.settings.php → controllers/main/controller.settings.php
Normal file → Executable file
@ -34,7 +34,9 @@
|
||||
*/
|
||||
|
||||
namespace Application\Controller;
|
||||
|
||||
use FuzeWorks\Core;
|
||||
use FuzeWorks\Exception\NotFoundException;
|
||||
use FuzeWorks\Priority;
|
||||
use FuzeWorks\WebController;
|
||||
|
||||
@ -45,27 +47,25 @@ class SettingsController extends WebController
|
||||
{
|
||||
// First collect all the known paths
|
||||
$paths = [];
|
||||
for ($i = Priority::getHighestPriority(); $i<=Priority::getLowestPriority(); $i++)
|
||||
for ($i = Priority::getHighestPriority(); $i <= Priority::getLowestPriority(); $i++)
|
||||
$paths[$i] = $this->config->getComponentPaths($i);
|
||||
|
||||
// And add the CorePath
|
||||
$paths[Priority::getLowestPriority()][] = Core::$coreDir . DS . 'Config';
|
||||
|
||||
// Then go over every individual paths
|
||||
$configFiles = [];
|
||||
foreach ($paths as $priority => $foldersArray)
|
||||
{
|
||||
foreach ($foldersArray as $folder)
|
||||
{
|
||||
foreach ($paths as $priority => $foldersArray) {
|
||||
foreach ($foldersArray as $folder) {
|
||||
// Get the contents from the folder
|
||||
$contents = array_diff(scandir($folder), array('..', '.'));
|
||||
|
||||
// Then go over the folders, and see which ones are an admin view
|
||||
foreach ($contents as $file)
|
||||
{
|
||||
foreach ($contents as $file) {
|
||||
// If the file matches the expected filename, add it to the list
|
||||
if (substr($file, 0, 7) === 'config.' && !isset($configFiles[$file]))
|
||||
$configFiles[$file] = ['folder' => $folder, 'priority' => substr(Priority::getPriority($priority), 10)];
|
||||
if (str_starts_with($file, 'config.')) {
|
||||
if (!isset($configFiles[$file]))
|
||||
$configFiles[$file] = [];
|
||||
|
||||
$configFiles[$file][] = ['folder' => $folder, 'priority' => substr(Priority::getPriority($priority), 10)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,4 +77,54 @@ class SettingsController extends WebController
|
||||
return $configFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a file
|
||||
*
|
||||
* @param string $fileName
|
||||
* @return array
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function fetchFile(string $fileName, int $selector): array
|
||||
{
|
||||
// Fetch files
|
||||
$files = $this->findSettingsFiles();
|
||||
|
||||
// Check if the file exists
|
||||
if (!isset($files[$fileName]))
|
||||
throw new NotFoundException("The requested settings file could not be found.");
|
||||
|
||||
// Select correct data
|
||||
$meta = $files[$fileName][$selector];
|
||||
|
||||
// Find the file
|
||||
$file = $meta['folder'] . DS . $fileName;
|
||||
if (!file_exists($file))
|
||||
throw new NotFoundException("The requested settings file could not be found.");
|
||||
|
||||
// Load the raw data
|
||||
$raw = file_get_contents($file);
|
||||
|
||||
// And try to load the editable data
|
||||
$data = include($file);
|
||||
|
||||
// Prepare output variable
|
||||
return ['name' => $fileName, 'directory' => $meta['folder'], 'raw' => $raw, 'data' => $data];
|
||||
}
|
||||
|
||||
protected function verifyFileData(array $fileData): bool
|
||||
{
|
||||
foreach ($fileData as $key => $val) {
|
||||
switch (gettype($val)) {
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'resource':
|
||||
case 'unknown type':
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
0
layouts/components/cache/layout.overview.latte
vendored
Normal file
0
layouts/components/cache/layout.overview.latte
vendored
Normal file
19
layouts/components/settings/layout.overview.latte
Normal file → Executable file
19
layouts/components/settings/layout.overview.latte
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
<div class="row">
|
||||
<div class="col-xl-12">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Configuration Files</h3>
|
||||
@ -18,14 +18,16 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{var $it = 0}
|
||||
{foreach $files as $fileName => $data}
|
||||
<tr>
|
||||
<td>{$iterator->getCounter()}</td>
|
||||
<tr n:foreach="$data as $entry">
|
||||
{var $it = $it + 1}
|
||||
<td>{$it}</td>
|
||||
<td>{$fileName}</td>
|
||||
<td>{$data['folder']}</td>
|
||||
<td>{$data['priority']}</td>
|
||||
<td><button type="button" class="btn btn-block btn-success">VIEW</button></td>
|
||||
<td><button type="button" class="btn btn-block btn-primary">EDIT</button></td>
|
||||
<td>{$entry['folder']}</td>
|
||||
<td>{$entry['priority']}</td>
|
||||
<td><a href="/{$adminKey}/settings/view/{$fileName}/{$iterator->counter0}"><button type="button" class="btn btn-block btn-success">VIEW</button></a></td>
|
||||
<td><a href="/{$adminKey}/settings/modify/{$fileName}/{$iterator->counter0}"><button type="button" class="btn btn-block btn-primary">EDIT</button></a></td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
@ -35,6 +37,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
63
layouts/components/settings/layout.view.latte
Executable file
63
layouts/components/settings/layout.view.latte
Executable file
@ -0,0 +1,63 @@
|
||||
{varType FuzeWorks\Forms\Form $form}
|
||||
{varType FuzeWorks\Forms\Field $field}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<!-- Custom Tabs -->
|
||||
<div class="card">
|
||||
<div class="card-header d-flex p-0">
|
||||
<h3 class="card-title p-3">{$config['name']}</h3>
|
||||
<ul class="nav nav-pills ml-auto p-2">
|
||||
{ifset $config['data']}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#data" data-toggle="tab">Data</a>
|
||||
</li>
|
||||
{/ifset}
|
||||
<li class="nav-item"><a class="nav-link {$config['data'] ? '' : 'active'}" href="#raw" data-toggle="tab">Raw</a></li>
|
||||
</ul>
|
||||
</div><!-- /.card-header -->
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
{foreach $form->getFields() as $field}
|
||||
{switch get_class($field)}
|
||||
{case "FuzeWorks\Forms\Fields\HiddenField", "FuzeWorks\Forms\Fields\SubmitField"}
|
||||
{$field|noescape}
|
||||
{case "FuzeWorks\Forms\Fields\CheckboxField"}
|
||||
<div class="form-check">
|
||||
{$field->addClass("form-check-input")|noescape}
|
||||
<label for="{$field->getId()}" class="form-check-label">{$field->getLabel()}</label>
|
||||
{if $field->isValidated() && !$field->isValid()}
|
||||
<small class="text-danger">{$field->getErrors()|implode}</small>
|
||||
{/if}
|
||||
</div>
|
||||
{default}
|
||||
<div class="form-group">
|
||||
<label for="{$field->getId()}">{$field->getLabel()}</label>
|
||||
{if $field->isValidated() && !$field->isValid()}
|
||||
{$field->class(["form-control", "is-invalid"])|noescape}
|
||||
<small class="text-danger">{$field->getErrors()|implode}</small>
|
||||
{elseif $field->isValidated() && $field->isValid()}
|
||||
{$field->class(["form-control", "is-valid"])|noescape}
|
||||
{else}
|
||||
{$field->addClass("form-control")|noescape}
|
||||
{/if}
|
||||
</div>
|
||||
{/switch}
|
||||
{/foreach}
|
||||
<div class="tab-pane {$config['data'] ? '' : 'active'}" id="raw">
|
||||
<textarea disabled style="min-width: 100%; height: 100%" oninput='resizeRawArea(this)'>{$config['raw']}</textarea>
|
||||
</div>
|
||||
<!-- /.tab-pane -->
|
||||
</div>
|
||||
<!-- /.tab-content -->
|
||||
</div><!-- /.card-body -->
|
||||
</div>
|
||||
<!-- ./card -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
<script>
|
||||
function resizeRawArea(jq_in) {
|
||||
jq_in.style.height = "";
|
||||
jq_in.style.height = jq_in.scrollHeight + 3 + "px";
|
||||
}
|
||||
</script>
|
12
layouts/components/test/layout.home.latte
Executable file
12
layouts/components/test/layout.home.latte
Executable file
@ -0,0 +1,12 @@
|
||||
{varType FuzeWorks\Forms\Form $form}
|
||||
<div class="col-md-6">
|
||||
<div class="card card-primary">
|
||||
<div class="card card-header">
|
||||
<h3 class="card-title">{$form->getLabel()}</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{$form|noescape}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
13
layouts/main/layout.error403.latte
Normal file
13
layouts/main/layout.error403.latte
Normal file
@ -0,0 +1,13 @@
|
||||
<div class="error-page">
|
||||
<h2 class="headline text-danger">403</h2>
|
||||
|
||||
<div class="error-content">
|
||||
<h3><i class="fas fa-exclamation-triangle text-danger"></i> Unauthorized! </h3>
|
||||
|
||||
<p>
|
||||
You do not have permission to view that page.
|
||||
Meanwhile, you may <a href="/{$adminKey}">return to dashboard</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.error-page -->
|
14
layouts/main/layout.error404.latte
Normal file
14
layouts/main/layout.error404.latte
Normal file
@ -0,0 +1,14 @@
|
||||
<div class="error-page">
|
||||
<h2 class="headline text-warning"> 404</h2>
|
||||
|
||||
<div class="error-content">
|
||||
<h3><i class="fas fa-exclamation-triangle text-warning"></i> Oops! Page not found.</h3>
|
||||
|
||||
<p>
|
||||
We could not find the page you were looking for.
|
||||
Meanwhile, you may <a href="/{$adminKey}">return to dashboard</a>.
|
||||
</p>
|
||||
</div>
|
||||
<!-- /.error-content -->
|
||||
</div>
|
||||
<!-- /.error-page -->
|
13
layouts/main/layout.error500.latte
Normal file
13
layouts/main/layout.error500.latte
Normal file
@ -0,0 +1,13 @@
|
||||
<div class="error-page">
|
||||
<h2 class="headline text-danger">500</h2>
|
||||
|
||||
<div class="error-content">
|
||||
<h3><i class="fas fa-exclamation-triangle text-danger"></i> Oops! Something went wrong.</h3>
|
||||
|
||||
<p>
|
||||
We will work on fixing that right away.
|
||||
Meanwhile, you may <a href="/{$adminKey}">return to dashboard</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.error-page -->
|
212
layouts/main/layout.panel.latte
Normal file → Executable file
212
layouts/main/layout.panel.latte
Normal file → Executable file
@ -1,29 +1,17 @@
|
||||
{varType FuzeWorks\Authentication\Model\Session $session}
|
||||
{varType bool $loadAsync}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>AdminLTE 3 | Dashboard</title>
|
||||
<title>{$serverName} | {$pageTitle}</title>
|
||||
<!-- Tell the browser to be responsive to screen width -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/plugins/fontawesome-free/css/all.min.css">
|
||||
<!-- Ionicons -->
|
||||
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||
<!-- Tempusdominus Bbootstrap 4 -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/plugins/tempusdominus-bootstrap-4/css/tempusdominus-bootstrap-4.min.css">
|
||||
<!-- iCheck -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
|
||||
<!-- JQVMap -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/plugins/jqvmap/jqvmap.min.css">
|
||||
<link rel="stylesheet" href="/{$adminKey}/lte_plugins/fontawesome-free/css/all.min.css">
|
||||
<!-- Theme style -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/dist/css/adminlte.min.css">
|
||||
<!-- overlayScrollbars -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/plugins/overlayScrollbars/css/OverlayScrollbars.min.css">
|
||||
<!-- Daterange picker -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/plugins/daterangepicker/daterangepicker.css">
|
||||
<!-- summernote -->
|
||||
<link rel="stylesheet" href="/{$adminKey}/plugins/summernote/summernote-bs4.css">
|
||||
<link rel="stylesheet" href="/{$adminKey}/lte_dist/css/adminlte.min.css">
|
||||
<!-- Google Font: Source Sans Pro -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
||||
</head>
|
||||
@ -38,113 +26,46 @@
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link">Home</a>
|
||||
<a href="/{$adminKey}" class="nav-link">Dashboard</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- SEARCH FORM -->
|
||||
<form class="form-inline ml-3">
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control form-control-navbar" type="search" placeholder="Search" aria-label="Search">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-navbar" type="submit">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- Messages Dropdown Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
{if $loadAsync}
|
||||
<li id="asyncWidget" class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-comments"></i>
|
||||
<span class="badge badge-danger navbar-badge">3</span>
|
||||
<i class="fa fa-list"></i>
|
||||
<span class="badge badge-warning navbar-badge">0</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<a href="#" class="dropdown-item">
|
||||
<!-- Message Start -->
|
||||
<div class="media">
|
||||
<img src="/{$adminKey}/dist/img/user1-128x128.jpg" alt="User Avatar" class="img-size-50 mr-3 img-circle">
|
||||
<div class="media-body">
|
||||
<h3 class="dropdown-item-title">
|
||||
Brad Diesel
|
||||
<span class="float-right text-sm text-danger"><i class="fas fa-star"></i></span>
|
||||
</h3>
|
||||
<p class="text-sm">Call me whenever you can...</p>
|
||||
<p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Message End -->
|
||||
</a>
|
||||
<span class="dropdown-item dropdown-header">Asynchronous tasks</span>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<!-- Message Start -->
|
||||
<div class="media">
|
||||
<img src="/{$adminKey}/dist/img/user8-128x128.jpg" alt="User Avatar" class="img-size-50 img-circle mr-3">
|
||||
<div class="media-body">
|
||||
<h3 class="dropdown-item-title">
|
||||
John Pierce
|
||||
<span class="float-right text-sm text-muted"><i class="fas fa-star"></i></span>
|
||||
</h3>
|
||||
<p class="text-sm">I got your message bro</p>
|
||||
<p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Message End -->
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<!-- Message Start -->
|
||||
<div class="media">
|
||||
<img src="/{$adminKey}/dist/img/user3-128x128.jpg" alt="User Avatar" class="img-size-50 img-circle mr-3">
|
||||
<div class="media-body">
|
||||
<h3 class="dropdown-item-title">
|
||||
Nora Silvester
|
||||
<span class="float-right text-sm text-warning"><i class="fas fa-star"></i></span>
|
||||
</h3>
|
||||
<p class="text-sm">The subject goes here</p>
|
||||
<p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Message End -->
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item dropdown-footer">See All Messages</a>
|
||||
<a href="/{$adminKey}/async" class="dropdown-item dropdown-footer">See all historic tasks</a>
|
||||
</div>
|
||||
</li>
|
||||
<!-- Notifications Dropdown Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-bell"></i>
|
||||
<span class="badge badge-warning navbar-badge">15</span>
|
||||
{/if}
|
||||
<li class="nav-item dropdown user-menu">
|
||||
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
|
||||
<img src="/{$adminKey}/lte_dist/img/user2-160x160.jpg" class="user-image img-circle elevation-2" alt="User Image">
|
||||
<span class="d-none d-md-inline">{$session->user->primaryEmail}</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<span class="dropdown-item dropdown-header">15 Notifications</span>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="fas fa-envelope mr-2"></i> 4 new messages
|
||||
<span class="float-right text-muted text-sm">3 mins</span>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="fas fa-users mr-2"></i> 8 friend requests
|
||||
<span class="float-right text-muted text-sm">12 hours</span>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="fas fa-file mr-2"></i> 3 new reports
|
||||
<span class="float-right text-muted text-sm">2 days</span>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item dropdown-footer">See All Notifications</a>
|
||||
</div>
|
||||
<ul class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<!-- User image -->
|
||||
<li class="user-header bg-primary">
|
||||
<img src="/{$adminKey}/lte_dist/img/user2-160x160.jpg" class="img-circle elevation-2" alt="User Image">
|
||||
<p>
|
||||
{$session->user->primaryEmail}
|
||||
<small>Member since -</small>
|
||||
</p>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#" role="button">
|
||||
<i class="fas fa-th-large"></i>
|
||||
</a>
|
||||
<!-- Menu Footer-->
|
||||
<li class="user-footer">
|
||||
<a href="/{$adminKey}/profile" class="btn btn-default btn-flat">Profile</a>
|
||||
<a href="{$authURL}/logout" class="btn btn-default btn-flat float-right">Sign out</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
@ -153,24 +74,14 @@
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-dark-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="index3.html" class="brand-link">
|
||||
<img src="/{$adminKey}/dist/img/AdminLTELogo.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3"
|
||||
<a href="/" class="brand-link">
|
||||
<img src="/{$adminKey}/lte_dist/img/AdminLTELogo.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3"
|
||||
style="opacity: .8">
|
||||
<span class="brand-text font-weight-light">AdminLTE 3</span>
|
||||
<span class="brand-text font-weight-light">{$serverName}</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar user panel (optional) -->
|
||||
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
|
||||
<div class="image">
|
||||
<img src="/{$adminKey}/dist/img/user2-160x160.jpg" class="img-circle elevation-2" alt="User Image">
|
||||
</div>
|
||||
<div class="info">
|
||||
<a href="#" class="d-block">Juris LLM</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-2">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
@ -196,12 +107,12 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0 text-dark">Dashboard</h1>
|
||||
<h1 class="m-0 text-dark">{$pageTitle}</h1>
|
||||
</div><!-- /.col -->
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="#">Home</a></li>
|
||||
<li class="breadcrumb-item active">Dashboard v1</li>
|
||||
<li class="breadcrumb-item"><a href="/{$adminKey}">Home</a></li>
|
||||
<li class="breadcrumb-item active">{$pageTitle}</li>
|
||||
</ol>
|
||||
</div><!-- /.col -->
|
||||
</div><!-- /.row -->
|
||||
@ -219,50 +130,29 @@
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
<footer class="main-footer">
|
||||
<strong>Copyright © 2013-2020 <a href="https://i15.nl">i15.nl</a>.</strong>
|
||||
<strong>Copyright © 2013-{date('Y')} <a href="https://i15.nl">i15.nl</a>.</strong>
|
||||
All rights reserved.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 1.3.0
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Control Sidebar -->
|
||||
<aside class="control-sidebar control-sidebar-dark">
|
||||
<!-- Control sidebar content goes here -->
|
||||
</aside>
|
||||
<!-- /.control-sidebar -->
|
||||
</div>
|
||||
<!-- ./wrapper -->
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="/{$adminKey}/plugins/jquery/jquery.min.js"></script>
|
||||
<!-- jQuery UI 1.11.4 -->
|
||||
<script src="/{$adminKey}/plugins/jquery-ui/jquery-ui.min.js"></script>
|
||||
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
|
||||
<script>
|
||||
$.widget.bridge('uibutton', $.ui.button)
|
||||
</script>
|
||||
<script src="/{$adminKey}/lte_plugins/jquery/jquery.min.js"></script>
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="/{$adminKey}/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- ChartJS -->
|
||||
<script src="/{$adminKey}/plugins/chart.js/Chart.min.js"></script>
|
||||
<!-- Sparkline -->
|
||||
<script src="/{$adminKey}/plugins/sparklines/sparkline.js"></script>
|
||||
<!-- JQVMap -->
|
||||
<script src="/{$adminKey}/plugins/jqvmap/jquery.vmap.min.js"></script>
|
||||
<script src="/{$adminKey}/plugins/jqvmap/maps/jquery.vmap.usa.js"></script>
|
||||
<!-- jQuery Knob Chart -->
|
||||
<script src="/{$adminKey}/plugins/jquery-knob/jquery.knob.min.js"></script>
|
||||
<!-- daterangepicker -->
|
||||
<script src="/{$adminKey}/plugins/moment/moment.min.js"></script>
|
||||
<script src="/{$adminKey}/plugins/daterangepicker/daterangepicker.js"></script>
|
||||
<!-- Tempusdominus Bootstrap 4 -->
|
||||
<script src="/{$adminKey}/plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js"></script>
|
||||
<!-- Summernote -->
|
||||
<script src="/{$adminKey}/plugins/summernote/summernote-bs4.min.js"></script>
|
||||
<!-- overlayScrollbars -->
|
||||
<script src="/{$adminKey}/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js"></script>
|
||||
<script src="/{$adminKey}/lte_plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="/{$adminKey}/dist/js/adminlte.js"></script>
|
||||
<script src="/{$adminKey}/lte_dist/js/adminlte.js"></script>
|
||||
{if $loadAsync}
|
||||
<script src="/{$adminKey}/admin_dist/async.ts"></script>
|
||||
{/if}
|
||||
<script>
|
||||
$.widget.bridge('uibutton', $.ui.button);
|
||||
</script>
|
||||
{ifset $footer}
|
||||
{$footer|noescape}
|
||||
{/ifset}
|
||||
</body>
|
||||
</html>
|
||||
|
332
src/FuzeWorks/Administration/AdminPlugin.php
Normal file → Executable file
332
src/FuzeWorks/Administration/AdminPlugin.php
Normal file → Executable file
@ -34,136 +34,252 @@
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration;
|
||||
use FuzeWorks\Administration\Attributes\DisplayAttribute;
|
||||
use FuzeWorks\Administration\Attributes\FooterCodeMethodAttribute;
|
||||
use FuzeWorks\Administration\Attributes\IconAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PermissionAttribute;
|
||||
use FuzeWorks\Authentication\AuthenticationPlugin;
|
||||
use FuzeWorks\Authentication\Model\Session;
|
||||
use FuzeWorks\Config;
|
||||
use FuzeWorks\ConfigORM\ConfigORM;
|
||||
use FuzeWorks\Controllers;
|
||||
use FuzeWorks\Core;
|
||||
use FuzeWorks\Event\LayoutLoadEvent;
|
||||
use FuzeWorks\Event\RouterCallViewEvent;
|
||||
use FuzeWorks\Event\RouteWebRequestEvent;
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Exception\ConfigException;
|
||||
use FuzeWorks\Exception\EventException;
|
||||
use FuzeWorks\Exception\Exception;
|
||||
use FuzeWorks\Exception\FactoryException;
|
||||
use FuzeWorks\Exception\HaltException;
|
||||
use FuzeWorks\Exception\LayoutException;
|
||||
use FuzeWorks\Exception\OutputException;
|
||||
use FuzeWorks\Exception\WebException;
|
||||
use FuzeWorks\Factory;
|
||||
use FuzeWorks\iPluginHeader;
|
||||
use FuzeWorks\Layout;
|
||||
use FuzeWorks\Logger;
|
||||
use FuzeWorks\Models;
|
||||
use FuzeWorks\Output;
|
||||
use FuzeWorks\Priority;
|
||||
use FuzeWorks\Resources;
|
||||
use FuzeWorks\Router;
|
||||
use FuzeWorks\View;
|
||||
use FuzeWorks\Views;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
|
||||
class AdminPlugin implements \FuzeWorks\iPluginHeader
|
||||
class AdminPlugin implements iPluginHeader
|
||||
{
|
||||
|
||||
private $pluginKey = 'admin';
|
||||
private Config $config;
|
||||
private Router $router;
|
||||
private Models $models;
|
||||
private Views $views;
|
||||
private Controllers $controllers;
|
||||
private AuthenticationPlugin $authPlugin;
|
||||
|
||||
/** @var Config */
|
||||
private $config;
|
||||
private string $pluginKey = 'admin';
|
||||
private string $pluginPath;
|
||||
private string $adminURL;
|
||||
private string $apiRoute;
|
||||
private string $webRoute;
|
||||
|
||||
/** @var Router */
|
||||
private $router;
|
||||
|
||||
/** @var Models */
|
||||
private $models;
|
||||
|
||||
/** @var Views */
|
||||
private $views;
|
||||
|
||||
/** @var Controllers */
|
||||
private $controllers;
|
||||
|
||||
/** @var ConfigORM */
|
||||
private $adminCFG;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $pluginPath;
|
||||
private ?Session $session = null;
|
||||
private bool $loadAsync = false;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws EventException
|
||||
* @throws FactoryException
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
// Make a listener for a web request
|
||||
Events::addListener([$this, 'routeWebRequestEventListener'], 'routeWebRequestEvent', Priority::NORMAL);
|
||||
$this->pluginPath = dirname(__DIR__, 3);
|
||||
}
|
||||
|
||||
public function routeWebRequestEventListener(RouteWebRequestEvent $event)
|
||||
{
|
||||
// If this request has nothing to do with the admin interface, don't bother routing the request
|
||||
if (substr($event->uriString, 0, strlen($this->pluginKey)) !== $this->pluginKey)
|
||||
// Load the admin configuration
|
||||
$this->config = Factory::getInstance('config');
|
||||
$this->config->addComponentPath($this->pluginPath, Priority::LOWEST);
|
||||
$adminCFG = $this->config->getConfig('admin');
|
||||
|
||||
// If admin is not enabled, stop here
|
||||
if (!$adminCFG->get('admin_enabled'))
|
||||
return;
|
||||
|
||||
Logger::log("Administration: observed admin request. Activating plugin.");
|
||||
// Register the event
|
||||
Events::addListener([$this, 'routeWebRequestEventListener'], 'routeWebRequestEvent', Priority::NORMAL);
|
||||
|
||||
// Now load the pluginKey
|
||||
$this->pluginKey = $adminCFG->get('admin_url');
|
||||
|
||||
// Settle admin URL
|
||||
$webURL = $this->config->getConfig("web")->get("base_url");
|
||||
$this->adminURL = $webURL . "/" . $this->pluginKey;
|
||||
|
||||
// Determine routing paths
|
||||
$this->webRoute = '^' . $this->pluginKey . '(|\/(?P<viewName>.*?)(|\/(?P<viewMethod>.*?)(|\/(?P<viewParameters>.*?))))';
|
||||
$this->apiRoute = '^' . $this->pluginKey . '(|\/(?P<viewName>.*?)(|\/(?P<viewMethod>.*?)(|\/(?P<viewParameters>.*?)))).json';
|
||||
|
||||
// Load the dependencies
|
||||
$this->config = Factory::getInstance('config');
|
||||
$this->router = Factory::getInstance('router');
|
||||
$this->models = Factory::getInstance('models');
|
||||
$this->views = Factory::getInstance('views');
|
||||
$this->controllers = Factory::getInstance('controllers');
|
||||
}
|
||||
|
||||
// Load the admin configuration
|
||||
$this->config->addComponentPath($this->pluginPath, Priority::LOWEST);
|
||||
$this->adminCFG = $this->config->getConfig('admin');
|
||||
|
||||
// If admin is not enabled, stop here
|
||||
if (!$this->adminCFG->get('admin_enabled'))
|
||||
return;
|
||||
|
||||
// Now load the pluginKey
|
||||
$this->pluginKey = $this->adminCFG->get('admin_url');
|
||||
/**
|
||||
* @param RouteWebRequestEvent $event
|
||||
* @return void
|
||||
* @throws FactoryException
|
||||
* @throws WebException
|
||||
*/
|
||||
public function routeWebRequestEventListener(RouteWebRequestEvent $event): void
|
||||
{
|
||||
Logger::log("Administration: observed web request. Activating plugin.");
|
||||
|
||||
// If it does, register everything
|
||||
/** @var Resources $resources */
|
||||
$resources = Factory::getInstance('resources');
|
||||
|
||||
// Serve the AdminLTE distribution files
|
||||
$adminLTE = $this->pluginPath . DS . 'vendor' . DS . 'almasaeed2010' . DS . 'adminlte';
|
||||
$resources->registerResources('admin/dist', $adminLTE . DS . 'dist');
|
||||
$resources->registerResources('admin/plugins', $adminLTE . DS . 'plugins');
|
||||
$adminLTE = dirname(Core::$coreDir, 4) . DS . 'vendor' . DS . 'almasaeed2010' . DS . 'adminlte';
|
||||
$resources->registerResources('admin/lte_dist', $adminLTE . DS . 'dist');
|
||||
$resources->registerResources('admin/lte_plugins', $adminLTE . DS . 'plugins');
|
||||
$resources->registerResources("admin/admin_dist", $this->pluginPath . DS . 'www' . DS . 'dist');
|
||||
|
||||
// @todo TEMPORARY!!
|
||||
//$resources->registerResources("lte_top", $adminLTE);
|
||||
|
||||
// And serve the actual pages
|
||||
$routeString = '^' . $this->pluginKey . '(|\/(?P<viewName>.*?)(|\/(?P<viewMethod>.*?)(|\/(?P<viewParameters>.*?))))';
|
||||
$this->router->addRoute($routeString, ['callable' => [$this, 'adminCallable']], Priority::HIGHEST);
|
||||
|
||||
// And add componentPaths for models, views, controllers
|
||||
$this->models->addComponentPath($this->pluginPath . DS . 'models', Priority::LOW);
|
||||
$this->views->addComponentPath($this->pluginPath . DS . 'views', Priority::LOW);
|
||||
$this->controllers->addComponentPath($this->pluginPath . DS . 'controllers', Priority::LOW);
|
||||
$this->router->addRoute('^' . $this->pluginKey, ['viewName' => 'dashboard', 'callable' => [$this, 'adminCallable']], Priority::HIGHEST);
|
||||
$this->router->addRoute($this->apiRoute, ['callable' => [$this, 'adminCallable']], Priority::HIGH);
|
||||
$this->router->addRoute($this->webRoute, ['callable' => [$this, 'adminCallable']], Priority::HIGH);
|
||||
}
|
||||
|
||||
public function adminCallable(array $matches, string $routeString)
|
||||
/**
|
||||
* @param array $matches
|
||||
* @param array $routeData
|
||||
* @param string $routeString
|
||||
* @return string|null
|
||||
* @throws EventException
|
||||
* @throws FactoryException
|
||||
* @throws LayoutException
|
||||
* @throws OutputException
|
||||
*/
|
||||
public function adminCallable(array $matches, array $routeData, string $routeString): ?string
|
||||
{
|
||||
Logger::log("AdminCallable called. Loading admin page.");
|
||||
|
||||
// Add componentPaths for models, views, controllers
|
||||
$this->models->addComponentPath($this->pluginPath . DS . 'models' . DS . 'main', Priority::LOW);
|
||||
$this->views->addComponentPath($this->pluginPath . DS . 'views' . DS . 'main', Priority::LOW);
|
||||
$this->controllers->addComponentPath($this->pluginPath . DS . 'controllers' . DS . 'main', Priority::LOW);
|
||||
|
||||
// Load layouts and assign componentPath, in case the loaded view needs access to it
|
||||
/** @var Layout $layouts */
|
||||
$layouts = Factory::getInstance('layouts');
|
||||
$layouts->addComponentPath($this->pluginPath . DS . 'layouts', Priority::LOW);
|
||||
|
||||
// And add a layoutLoadEventListener, to add global administration variables
|
||||
Events::addListener([$this, 'layoutLoadEventListener'], 'layoutLoadEvent', Priority::NORMAL);
|
||||
Events::addListener([$this, 'layoutLoadEventListener'], 'layoutLoadEvent', Priority::HIGH);
|
||||
Events::addListener([$this, 'verifyViewPermissions'], 'routerCallViewEvent', Priority::HIGH);
|
||||
Events::addListener([$this, 'logViewNameAndIcon'], 'routerCallViewEvent', Priority::NORMAL);
|
||||
|
||||
if (class_exists("\FuzeWorks\Async\Tasks"))
|
||||
{
|
||||
// Mark async to be loaded
|
||||
$this->loadAsync = true;
|
||||
|
||||
// Add componentPaths for models, views, controllers
|
||||
$this->models->addComponentPath($this->pluginPath . DS . 'models' . DS . 'async', Priority::LOW);
|
||||
$this->views->addComponentPath($this->pluginPath . DS . 'views' . DS . 'async', Priority::LOW);
|
||||
$this->controllers->addComponentPath($this->pluginPath . DS . 'controllers' . DS . 'async', Priority::LOW);
|
||||
}
|
||||
|
||||
// Load the current session
|
||||
/** @var Output $output */
|
||||
$this->authPlugin = Factory::getInstance("plugins")->get('auth');
|
||||
$output = Factory::getInstance("output");
|
||||
|
||||
// Redirect the user to login if they're not logged in
|
||||
$this->session = $this->authPlugin->sessions->start();
|
||||
if ($this->session->user->id === "0")
|
||||
{
|
||||
$output->setHeader("Location: " . $this->authPlugin->getAuthenticationURL() . "/login?location=" . $this->getAdminURL());
|
||||
return "";
|
||||
}
|
||||
|
||||
// Let's generate the sidebar
|
||||
$finder = new PageFinder();
|
||||
$sidebar = $finder->generateSidebar();
|
||||
$sidebar = $finder->generateSidebar($this->session);
|
||||
$footer = "";
|
||||
|
||||
// Afterwards, pass on to the admin view and its contents
|
||||
Logger::log("Forwarding request to Router::defaultCallable().");
|
||||
$matches['viewType'] = 'admin';
|
||||
$content = $this->router->defaultCallable($matches, $routeString);
|
||||
|
||||
// Reset and assign
|
||||
// Determine viewType
|
||||
if ($routeString === $this->apiRoute)
|
||||
$routeData['viewType'] = 'AdminAPI';
|
||||
else
|
||||
$routeData['viewType'] = 'admin';
|
||||
|
||||
try {
|
||||
// Fetch content from requested view
|
||||
$content = $this->router->defaultCallable($matches, $routeData, $routeString);
|
||||
|
||||
// If content is false, nothing is found and should return 404
|
||||
if (is_bool($content) && $content === false)
|
||||
{
|
||||
$output->setStatusHeader(404);
|
||||
$content = $layouts->get("main/error404");
|
||||
$this->selectedMethodName = "Not found";
|
||||
}
|
||||
|
||||
// And check for footer code
|
||||
if (!empty($this->footerMethod))
|
||||
{
|
||||
if (!method_exists($this->selectedView, $this->footerMethod))
|
||||
throw new Exception("Could not load view. Requested footerMethod not found.");
|
||||
|
||||
$footer = call_user_func_array([$this->selectedView, $this->footerMethod], []);
|
||||
}
|
||||
|
||||
} catch (HaltException $e) {
|
||||
$output->setStatusHeader(403);
|
||||
$content = $layouts->get("main/error403");
|
||||
$this->selectedMethodName = "Unauthorized";
|
||||
} catch (Exception|\Throwable $e) {
|
||||
Logger::exceptionHandler($e, false);
|
||||
$output->setStatusHeader(500);
|
||||
$content = $layouts->get("main/error500");
|
||||
$this->selectedMethodName = "Fatal error";
|
||||
}
|
||||
|
||||
// If an api is requested, return the content as a json object
|
||||
if ($routeData['viewType'] === 'AdminAPI')
|
||||
{
|
||||
$output->setContentType('json');
|
||||
return json_encode($content);
|
||||
}
|
||||
|
||||
// Otherwise, load the panel and return that
|
||||
Logger::log("Generating panel wrapper.");
|
||||
$layouts->reset(false);
|
||||
$layouts->assign("pageTitle", $this->selectedMethodName);
|
||||
$layouts->assign("pageIcon", $this->selectedMethodIcon);
|
||||
$layouts->assign('sidebar', $sidebar);
|
||||
$layouts->assign('content', $content);
|
||||
$layouts->assign("footer", $footer);
|
||||
|
||||
// And load the page
|
||||
Logger::log("Forwarding output back to Router.");
|
||||
$page = $layouts->get('main/panel');
|
||||
return $page;
|
||||
return $layouts->get('main/panel');
|
||||
}
|
||||
|
||||
public function getAdminURL(): string
|
||||
{
|
||||
return $this->adminURL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,6 +292,98 @@ class AdminPlugin implements \FuzeWorks\iPluginHeader
|
||||
public function layoutLoadEventListener(LayoutLoadEvent $event)
|
||||
{
|
||||
$event->assign('adminKey', $this->pluginKey);
|
||||
$event->assign('session', $this->session);
|
||||
$event->assign('authURL', $this->authPlugin->getAuthenticationURL());
|
||||
$event->assign("loadAsync", $this->loadAsync);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Listener for RouterCallViewEvent
|
||||
*
|
||||
* Verifies that the current user has access to the requested methods.
|
||||
*
|
||||
* @param RouterCallViewEvent $event
|
||||
* @return RouterCallViewEvent
|
||||
* @throws ReflectionException
|
||||
* @throws HaltException
|
||||
*/
|
||||
public function verifyViewPermissions(RouterCallViewEvent $event): RouterCallViewEvent
|
||||
{
|
||||
// Load reflector
|
||||
$reflector = new ReflectionClass(get_class($event->view));
|
||||
|
||||
// Pass over each requested method
|
||||
for ($i = Priority::getHighestPriority(); $i <= Priority::getLowestPriority(); $i++) {
|
||||
if (!isset($event->viewMethods[$i]))
|
||||
continue;
|
||||
|
||||
foreach ($event->viewMethods[$i] as $key => $method)
|
||||
{
|
||||
// If the method doesn't exist, skip it in general
|
||||
if (!method_exists($event->view, $method))
|
||||
{
|
||||
unset($event->viewMethods[$i][$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the method exists, verify permission
|
||||
$methodReflector = $reflector->getMethod($method);
|
||||
$permissionAttributes = $methodReflector->getAttributes(PermissionAttribute::class);
|
||||
if (!empty($permissionAttributes))
|
||||
{
|
||||
// Fetch nodes
|
||||
$nodes = $permissionAttributes[0]->newInstance()->getValue();
|
||||
|
||||
// Check if any of the nodes are permitted
|
||||
$found = false;
|
||||
foreach ($nodes as $node)
|
||||
if ($this->session->hasPermission($node))
|
||||
$found = true;
|
||||
|
||||
// If not, skip
|
||||
if (!$found)
|
||||
{
|
||||
|
||||
Logger::logWarning("Current user does not have permission for the requested method. Blocking.");
|
||||
$event->setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
protected string $selectedMethodName = "";
|
||||
protected string $selectedMethodIcon = "";
|
||||
protected string $footerMethod = "";
|
||||
protected View $selectedView;
|
||||
|
||||
public function logViewNameAndIcon(RouterCallViewEvent $event): RouterCallViewEvent
|
||||
{
|
||||
$reflector = new ReflectionClass(get_class($event->view));
|
||||
$this->selectedView = $event->view;
|
||||
for ($i = Priority::getHighestPriority(); $i <= Priority::getLowestPriority(); $i++)
|
||||
{
|
||||
if (!isset($event->viewMethods[$i]))
|
||||
continue;
|
||||
|
||||
foreach ($event->viewMethods[$i] as $key => $method)
|
||||
{
|
||||
$methodReflector = $reflector->getMethod($method);
|
||||
|
||||
// Check for display attribute.
|
||||
$displayAttributes = $methodReflector->getAttributes(DisplayAttribute::class);
|
||||
$iconAttributes = $methodReflector->getAttributes(IconAttribute::class);
|
||||
$footerAttributes = $methodReflector->getAttributes(FooterCodeMethodAttribute::class);
|
||||
$this->selectedMethodName = !empty($displayAttributes) ? $displayAttributes[0]->newInstance()->getValue() : ucfirst($methodReflector->getName());
|
||||
$this->selectedMethodIcon = !empty($iconAttributes) ? $iconAttributes[0]->newInstance()->getValue() : "";
|
||||
$this->footerMethod = !empty($footerAttributes) ? $footerAttributes[0]->newInstance()->getvalue() : "";
|
||||
}
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,7 +391,7 @@ class AdminPlugin implements \FuzeWorks\iPluginHeader
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'FuzeWorksAdministration';
|
||||
return 'admin';
|
||||
}
|
||||
|
||||
/**
|
||||
|
21
src/FuzeWorks/Administration/AdminView.php
Normal file → Executable file
21
src/FuzeWorks/Administration/AdminView.php
Normal file → Executable file
@ -34,6 +34,9 @@
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration;
|
||||
use FuzeWorks\Authentication\AuthenticationPlugin;
|
||||
use FuzeWorks\Authentication\Model\Session;
|
||||
use FuzeWorks\Authentication\Model\Users;
|
||||
use FuzeWorks\Factory;
|
||||
use FuzeWorks\Layout;
|
||||
use FuzeWorks\Priority;
|
||||
@ -41,21 +44,27 @@ use FuzeWorks\WebView;
|
||||
|
||||
abstract class AdminView extends WebView
|
||||
{
|
||||
|
||||
/** @var Layout */
|
||||
protected $layouts;
|
||||
protected Layout $layouts;
|
||||
protected Session $session;
|
||||
protected Users $users;
|
||||
|
||||
/**
|
||||
* The priority of this AdminView.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $priority = Priority::NORMAL;
|
||||
protected int $priority = Priority::NORMAL;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Set layouts
|
||||
$this->layouts = Factory::getInstance('layouts');
|
||||
|
||||
/** @var AuthenticationPlugin $plugin */
|
||||
$plugin = $this->plugins->get('auth');
|
||||
|
||||
// Set current session
|
||||
$this->users = $plugin->users;
|
||||
$this->session = $plugin->sessions->getCurrentSession();
|
||||
}
|
||||
}
|
41
src/FuzeWorks/Administration/Attributes/AdminAttribute.php
Executable file
41
src/FuzeWorks/Administration/Attributes/AdminAttribute.php
Executable file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksAdministration
|
||||
*
|
||||
* Copyright (C) 2013-2021 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.0.0
|
||||
*
|
||||
* @version Version 1.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
|
||||
interface AdminAttribute
|
||||
{
|
||||
|
||||
public function getValue();
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksAdministration
|
||||
*
|
||||
* Copyright (C) 2013-2023 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2023, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.0.0
|
||||
*
|
||||
* @version Version 1.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute]
|
||||
class DashboardAttribute implements AdminAttribute
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
57
src/FuzeWorks/Administration/Attributes/DisplayAttribute.php
Executable file
57
src/FuzeWorks/Administration/Attributes/DisplayAttribute.php
Executable file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksAdministration
|
||||
*
|
||||
* Copyright (C) 2013-2021 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.0.0
|
||||
*
|
||||
* @version Version 1.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
use Attribute;
|
||||
|
||||
#[Attribute]
|
||||
class DisplayAttribute implements AdminAttribute
|
||||
{
|
||||
|
||||
const VALUE = '';
|
||||
|
||||
private string $value;
|
||||
|
||||
public function __construct(string $value = '')
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksAdministration
|
||||
*
|
||||
* Copyright (C) 2013-2021 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.0.0
|
||||
*
|
||||
* @version Version 1.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
use Attribute;
|
||||
|
||||
#[Attribute]
|
||||
class FooterCodeMethodAttribute implements AdminAttribute
|
||||
{
|
||||
|
||||
const VALUE = '';
|
||||
|
||||
private string $value;
|
||||
|
||||
public function __construct(string $value = '')
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
44
src/FuzeWorks/Administration/Attributes/HiddenAttribute.php
Executable file
44
src/FuzeWorks/Administration/Attributes/HiddenAttribute.php
Executable file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksAdministration
|
||||
*
|
||||
* Copyright (C) 2013-2021 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.0.0
|
||||
*
|
||||
* @version Version 1.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
use Attribute;
|
||||
|
||||
#[Attribute]
|
||||
class HiddenAttribute implements AdminAttribute
|
||||
{
|
||||
public function getValue(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
53
src/FuzeWorks/Administration/Attributes/IconAttribute.php
Executable file
53
src/FuzeWorks/Administration/Attributes/IconAttribute.php
Executable file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksAdministration
|
||||
*
|
||||
* Copyright (C) 2013-2021 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.0.0
|
||||
*
|
||||
* @version Version 1.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
use Attribute;
|
||||
|
||||
#[Attribute]
|
||||
class IconAttribute implements AdminAttribute
|
||||
{
|
||||
|
||||
private string $value;
|
||||
|
||||
public function __construct(string $value = '')
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksWorkspace.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2022 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2022, i15. (http://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link https://i15.nl
|
||||
* @since Version 2.0.0
|
||||
*
|
||||
* @version Version 2.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
use Attribute;
|
||||
|
||||
#[Attribute]
|
||||
class PermissionAttribute implements AdminAttribute
|
||||
{
|
||||
private array $nodes;
|
||||
|
||||
public function __construct(array $nodes = [])
|
||||
{
|
||||
$this->nodes = $nodes;
|
||||
}
|
||||
|
||||
public function getValue(): array
|
||||
{
|
||||
return $this->nodes;
|
||||
}
|
||||
|
||||
}
|
54
src/FuzeWorks/Administration/Attributes/PriorityAttribute.php
Executable file
54
src/FuzeWorks/Administration/Attributes/PriorityAttribute.php
Executable file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksAdministration
|
||||
*
|
||||
* Copyright (C) 2013-2021 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.0.0
|
||||
*
|
||||
* @version Version 1.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Attributes;
|
||||
use Attribute;
|
||||
use FuzeWorks\Priority;
|
||||
|
||||
#[Attribute]
|
||||
class PriorityAttribute implements AdminAttribute
|
||||
{
|
||||
|
||||
private int $priority;
|
||||
|
||||
public function __construct(int $value = Priority::NORMAL)
|
||||
{
|
||||
$this->priority = $value;
|
||||
}
|
||||
|
||||
public function getValue(): int
|
||||
{
|
||||
return $this->priority;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksWorkspace.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2022 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2022, i15. (http://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link https://i15.nl
|
||||
* @since Version 2.0.0
|
||||
*
|
||||
* @version Version 2.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Exceptions;
|
||||
|
||||
use FuzeWorks\Exception\PluginException;
|
||||
|
||||
class AdminPluginException extends PluginException
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorksWorkspace.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2022 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2022, i15. (http://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link https://i15.nl
|
||||
* @since Version 2.0.0
|
||||
*
|
||||
* @version Version 2.0.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration\Exceptions;
|
||||
|
||||
class UnauthorizedException extends AdminPluginException
|
||||
{
|
||||
|
||||
}
|
218
src/FuzeWorks/Administration/PageFinder.php
Normal file → Executable file
218
src/FuzeWorks/Administration/PageFinder.php
Normal file → Executable file
@ -35,13 +35,19 @@
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Administration;
|
||||
use FuzeWorks\Administration\Attributes\DisplayAttribute;
|
||||
use FuzeWorks\Administration\Attributes\HiddenAttribute;
|
||||
use FuzeWorks\Administration\Attributes\IconAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PermissionAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PriorityAttribute;
|
||||
use FuzeWorks\Administration\Events\AdminFindViewsEvent;
|
||||
use FuzeWorks\Administration\Events\AdminGenerateSidebarEvent;
|
||||
use FuzeWorks\Authentication\Model\Session;
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Factory;
|
||||
use FuzeWorks\Logger;
|
||||
use FuzeWorks\Priority;
|
||||
use FuzeWorks\Views;
|
||||
use phpDocumentor\Reflection\DocBlockFactory;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
@ -50,39 +56,56 @@ class PageFinder
|
||||
{
|
||||
|
||||
|
||||
protected Session $session;
|
||||
|
||||
/**
|
||||
* Generates an array of all sidebar elements.
|
||||
*
|
||||
* First searches for all the available AdminViews. Then parses over all their methods and populates the array
|
||||
* using each method's individual docblock.
|
||||
* using each method's attributes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function generateSidebar(): array
|
||||
public function generateSidebar(Session $session): array
|
||||
{
|
||||
$this->session = $session;
|
||||
|
||||
Logger::log("Generating sidebar...");
|
||||
$event = Events::fireEvent('adminGenerateSidebarEvent');
|
||||
if ($event->isCancelled())
|
||||
return [];
|
||||
|
||||
// First find all views
|
||||
$viewFileList = $this->findViews();
|
||||
Logger::log("Found " . count($viewFileList) . ' admin views.');
|
||||
$views = $this->findViews();
|
||||
Logger::log("Found " . count($views) . ' admin views.');
|
||||
|
||||
// Then sort all those views into methods in the sidebar
|
||||
$sorted = $this->sort($viewFileList);
|
||||
$sorted = $this->sortSidebar($views);
|
||||
|
||||
// Log the result and return
|
||||
Logger::log("Found " . count($sorted) . ' entries for sidebar.');
|
||||
return $sorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all views that have methods with attributes of a specific kind.
|
||||
*
|
||||
* @param string $attributeClass
|
||||
* @return string[]
|
||||
*/
|
||||
public function findViewsWithAttribute(string $attributeClass): array
|
||||
{
|
||||
// First find all admin views
|
||||
$views = $this->findViews();
|
||||
return $this->sortByAttribute($views, $attributeClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse over every view component path and find all admin views.
|
||||
*
|
||||
* Return a file list.
|
||||
*
|
||||
* @return array
|
||||
* @return string[]
|
||||
*/
|
||||
protected function findViews(): array
|
||||
{
|
||||
@ -95,7 +118,7 @@ class PageFinder
|
||||
$paths[$i] = $views->getComponentPaths($i);
|
||||
|
||||
// Then go over every individual paths
|
||||
$viewFiles = [];
|
||||
$views = [];
|
||||
foreach ($paths as $priority => $foldersArray)
|
||||
{
|
||||
foreach ($foldersArray as $folder)
|
||||
@ -107,44 +130,79 @@ class PageFinder
|
||||
foreach ($contents as $file)
|
||||
{
|
||||
// If the file matches the expected filename, add it to the list
|
||||
if (substr($file, 0, 11) === 'view.admin.' && !isset($viewFiles[$file]))
|
||||
$viewFiles[$file] = $folder . DS . $file;
|
||||
if (!str_starts_with($file, 'view.admin.'))
|
||||
continue;
|
||||
|
||||
// Attempt to load the view
|
||||
$viewFile = $folder . DS . $file;
|
||||
$id = substr($file, 11, -4);
|
||||
$className = 'Application\View\\' . ucfirst($id) . 'AdminView';
|
||||
require_once($viewFile);
|
||||
if (!class_exists($className))
|
||||
continue;
|
||||
|
||||
$views[] = $className;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $viewFiles;
|
||||
return $views;
|
||||
}
|
||||
|
||||
protected function sort(array $viewFileList): array
|
||||
/**
|
||||
* Returns all views which have methods which have Attributes with the attributeClassName
|
||||
*
|
||||
* @param string[] $views
|
||||
* @param string $attributeClassName
|
||||
* @return string[]
|
||||
*/
|
||||
protected function sortByAttribute(array $views, string $attributeClassName): array
|
||||
{
|
||||
// Reflection docblock factory
|
||||
$factory = DocBlockFactory::createInstance();
|
||||
$out = [];
|
||||
foreach ($views as $view)
|
||||
{
|
||||
try {
|
||||
$reflector = new ReflectionClass($view);
|
||||
} catch (ReflectionException $e) {
|
||||
// If reflector doesn't work, simply ignore it.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the class actually inherits AdminView
|
||||
if (!$reflector->isSubclassOf(AdminView::class))
|
||||
continue;
|
||||
|
||||
// Select all methods
|
||||
$methods = $reflector->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $method)
|
||||
if (!empty($method->getAttributes($attributeClassName)))
|
||||
$out[] = $view;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
protected function sortSidebar(array $views): array
|
||||
{
|
||||
// Start sorting all methods
|
||||
$entries = [];
|
||||
foreach ($viewFileList as $viewId => $viewFile)
|
||||
foreach ($views as $view)
|
||||
{
|
||||
// Load the file
|
||||
require_once $viewFile;
|
||||
|
||||
// Determine the className
|
||||
$id = substr($viewId, 11, -4);
|
||||
$className = 'Application\View\\' . ucfirst($id) . 'AdminView';
|
||||
|
||||
// Try and reflect on this class.
|
||||
try {
|
||||
$reflector = new ReflectionClass($className);
|
||||
$reflector = new ReflectionClass($view);
|
||||
} catch (ReflectionException $e) {
|
||||
// If that doesn't work, simply ignore it. Don't drag the whole interface down.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if this class actually inherits AdminView
|
||||
$parent = $reflector->getParentClass();
|
||||
if ($parent === false || $parent->getName() !== 'FuzeWorks\Administration\AdminView')
|
||||
if (!$reflector->isSubclassOf("FuzeWorks\Administration\AdminView"))
|
||||
continue;
|
||||
|
||||
// Determine view Id
|
||||
$id = strtolower(substr($reflector->getShortName(), 0, -9));
|
||||
|
||||
// Select all methods
|
||||
$methods = $reflector->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
|
||||
@ -154,77 +212,75 @@ class PageFinder
|
||||
$entry = [
|
||||
'url' => ($id !== 'index' ? $id : '') . ($method->getName() !== 'index' ? '/' . $method->getName() : ''),
|
||||
'priority' => Priority::NORMAL,
|
||||
'display' => $reflector->getShortName() . '/' . $method->getName(),
|
||||
'display' => $reflector->getShortName() . '::' . $method->getName(),
|
||||
'icon' => 'round'
|
||||
];
|
||||
|
||||
// Only allow the methods in the actual class. Not from the parent method.
|
||||
if ($method->class !== $className)
|
||||
if ($method->class !== $view)
|
||||
continue;
|
||||
|
||||
// Then fetch the docComments.
|
||||
$docComment = $method->getDocComment();
|
||||
if ($docComment !== false)
|
||||
{
|
||||
$docBlock = $factory->create($docComment);
|
||||
$docTags = $docBlock->getTags();
|
||||
|
||||
// Find known tags
|
||||
$hidden = $docBlock->getTagsByName('hidden');
|
||||
$display = $docBlock->getTagsByName('display');
|
||||
$icon = $docBlock->getTagsByName('icon');
|
||||
$priority = $docBlock->getTagsByName('priority');
|
||||
|
||||
// First test for hidden. If found, it should not be added to the sidebar
|
||||
if (!empty($hidden))
|
||||
// Read attributes
|
||||
// First read hidden attribute. If present, skip this method
|
||||
$hiddenAttributes = $method->getAttributes(HiddenAttribute::class);
|
||||
if (!empty($hiddenAttributes))
|
||||
continue;
|
||||
|
||||
// Then test for display
|
||||
if (!empty($display))
|
||||
$entry['display'] = (string) $display[0];
|
||||
|
||||
// Then test for icon
|
||||
if (!empty($icon))
|
||||
$entry['icon'] = (string) $icon[0];
|
||||
|
||||
// Then test for priority
|
||||
if (!empty($priority))
|
||||
// Then check for permissions
|
||||
$permissionAttributes = $method->getAttributes(PermissionAttribute::class);
|
||||
if (!empty($permissionAttributes))
|
||||
{
|
||||
$priority = (string) $priority[0];
|
||||
switch ($priority) {
|
||||
case 'Priority::LOWEST':
|
||||
$entry['priority'] = 5;
|
||||
break;
|
||||
case 'Priority::LOW':
|
||||
$entry['priority'] = 4;
|
||||
break;
|
||||
case 'Priority::NORMAL':
|
||||
$entry['priority'] = 3;
|
||||
break;
|
||||
case 'Priority::HIGH':
|
||||
$entry['priority'] = 2;
|
||||
break;
|
||||
case 'Priority::HIGHEST':
|
||||
$entry['priority'] = 1;
|
||||
break;
|
||||
case 'Priority::MONITOR':
|
||||
$entry['priority'] = 0;
|
||||
break;
|
||||
default:
|
||||
Logger::logError("Method " . $reflector->getName() . '::' . $method->getName() . ' has invalid value for @priority.');
|
||||
$entry['priority'] = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Fetch nodes
|
||||
$nodes = $permissionAttributes[0]->newInstance()->getValue();
|
||||
|
||||
// Check if any of the nodes are permitted
|
||||
$found = false;
|
||||
foreach ($nodes as $node)
|
||||
if ($this->session->hasPermission($node))
|
||||
$found = true;
|
||||
|
||||
// If not, skip
|
||||
if (!$found)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Then check for display attribute.
|
||||
$displayAttributes = $method->getAttributes(DisplayAttribute::class);
|
||||
if (!empty($displayAttributes))
|
||||
$entry['display'] = $displayAttributes[0]->newInstance()->getValue();
|
||||
|
||||
// Then check for icon
|
||||
$iconAttributes = $method->getAttributes(IconAttribute::class);
|
||||
if (!empty($iconAttributes))
|
||||
$entry['icon'] = $iconAttributes[0]->newInstance()->getValue();
|
||||
|
||||
// Then check for priority
|
||||
$priorityAttributes = $method->getAttributes(PriorityAttribute::class);
|
||||
if (!empty($priorityAttributes))
|
||||
$entry['priority'] = $priorityAttributes[0]->newInstance()->getValue();
|
||||
|
||||
// Add priority
|
||||
if (!isset($entries[$entry['priority']]))
|
||||
$entries[$entry['priority']] = [];
|
||||
|
||||
// Write to entries
|
||||
$entries[] = $entry;
|
||||
$entries[$entry['priority']][] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
// And finally return those
|
||||
return $entries;
|
||||
// Sort by priority
|
||||
$out = [];
|
||||
for ($i = Priority::getHighestPriority(); $i <= Priority::getLowestPriority(); $i++) {
|
||||
if (!isset($entries[$i]))
|
||||
continue;
|
||||
|
||||
$p = $entries[$i];
|
||||
foreach ($p as $entry)
|
||||
$out[] = $entry;
|
||||
}
|
||||
|
||||
// And finally return the sidebar entries
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
0
test/bootstrap.php
Normal file → Executable file
0
test/bootstrap.php
Normal file → Executable file
76
views/async/view.admin.async.php
Normal file
76
views/async/view.admin.async.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* i15Site.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2022 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2022, i15. (http://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link https://i15.nl
|
||||
* @since Version 2.0.0
|
||||
*
|
||||
* @version Version 2.0.0
|
||||
*/
|
||||
|
||||
namespace Application\View;
|
||||
use Application\Controller\AsyncController;
|
||||
use FuzeWorks\Administration\AdminView;
|
||||
use FuzeWorks\Administration\Attributes\DisplayAttribute;
|
||||
use FuzeWorks\Administration\Attributes\HiddenAttribute;
|
||||
use FuzeWorks\Async\Tasks;
|
||||
use FuzeWorks\Controller;
|
||||
|
||||
class AsyncAdminView extends AdminView
|
||||
{
|
||||
/**
|
||||
* @var AsyncController
|
||||
*/
|
||||
protected Controller $controller;
|
||||
protected Tasks $tasks;
|
||||
|
||||
#[HiddenAttribute]
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
/** @var Tasks $lib */
|
||||
$lib = $this->libraries->get("tasks");
|
||||
$this->tasks = $lib;
|
||||
}
|
||||
|
||||
#[HiddenAttribute]
|
||||
#[DisplayAttribute("Overview")]
|
||||
public function index()
|
||||
{
|
||||
// Read out all tasks
|
||||
$storage = $this->tasks->getTaskStorage();
|
||||
$tasks = $storage->readTasks();
|
||||
|
||||
// And assign them
|
||||
$this->layouts->assign("tasks", $tasks);
|
||||
return json_encode($tasks);
|
||||
}
|
||||
|
||||
}
|
67
views/async/view.adminapi.async.php
Normal file
67
views/async/view.adminapi.async.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* i15Site.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2022 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2022, i15. (http://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link https://i15.nl
|
||||
* @since Version 2.0.0
|
||||
*
|
||||
* @version Version 2.0.0
|
||||
*/
|
||||
|
||||
namespace Application\View;
|
||||
|
||||
use Application\Controller\AsyncController;
|
||||
use FuzeWorks\Administration\AdminView;
|
||||
use FuzeWorks\Async\Tasks;
|
||||
use FuzeWorks\Controller;
|
||||
|
||||
class AsyncAdminApiView extends AdminView
|
||||
{
|
||||
|
||||
/**
|
||||
* @var AsyncController
|
||||
*/
|
||||
protected Controller $controller;
|
||||
protected Tasks $tasks;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
/** @var Tasks $lib */
|
||||
$lib = $this->libraries->get("tasks");
|
||||
$this->tasks = $lib;
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return ["Hello world"];
|
||||
}
|
||||
|
||||
}
|
32
views/main/view.admin.cache.php
Normal file
32
views/main/view.admin.cache.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Application\View;
|
||||
|
||||
use Application\Controller\CacheController;
|
||||
use FuzeWorks\Administration\AdminView;
|
||||
use FuzeWorks\Administration\Attributes\DisplayAttribute;
|
||||
use FuzeWorks\Administration\Attributes\HiddenAttribute;
|
||||
use FuzeWorks\Administration\Attributes\IconAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PermissionAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PriorityAttribute;
|
||||
use FuzeWorks\Controller;
|
||||
use FuzeWorks\Factory;
|
||||
use FuzeWorks\ObjectStorage\ObjectStorageComponent;
|
||||
use FuzeWorks\Priority;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
class CacheAdminView extends AdminView
|
||||
{
|
||||
|
||||
/** @var CacheController $controller */
|
||||
protected Controller $controller;
|
||||
#[DisplayAttribute("ObjectStorage"), IconAttribute("server"), PriorityAttribute(Priority::LOW)]
|
||||
#[HiddenAttribute]
|
||||
#[PermissionAttribute(["ADMIN"])]
|
||||
public function index()
|
||||
{
|
||||
$items = $this->controller->getCacheItems();
|
||||
return json_encode($items);
|
||||
}
|
||||
|
||||
}
|
42
views/view.admin.settings.php → views/main/view.admin.dashboard.php
Normal file → Executable file
42
views/view.admin.settings.php → views/main/view.admin.dashboard.php
Normal file → Executable file
@ -34,43 +34,33 @@
|
||||
*/
|
||||
|
||||
namespace Application\View;
|
||||
use Application\Controller\SettingsController;
|
||||
use Application\Controller\DashboardController;
|
||||
use FuzeWorks\Administration\AdminView;
|
||||
use FuzeWorks\Administration\Attributes\DashboardAttribute;
|
||||
use FuzeWorks\Administration\Attributes\DisplayAttribute;
|
||||
use FuzeWorks\Administration\Attributes\HiddenAttribute;
|
||||
use FuzeWorks\Administration\Attributes\IconAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PriorityAttribute;
|
||||
use FuzeWorks\Controller;
|
||||
use FuzeWorks\Priority;
|
||||
|
||||
class SettingsAdminView extends AdminView
|
||||
class DashboardAdminView extends AdminView
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SettingsController
|
||||
* @var DashboardController
|
||||
*/
|
||||
protected $controller;
|
||||
protected Controller $controller;
|
||||
|
||||
/**
|
||||
* Displays a list of settings files
|
||||
*
|
||||
* @display Settings
|
||||
* @icon cog
|
||||
* @priority Priority::LOW
|
||||
*/
|
||||
#[DisplayAttribute("Dashboard"), IconAttribute("tachometer-alt"), PriorityAttribute(Priority::HIGHEST)]
|
||||
public function index()
|
||||
{
|
||||
$files = $this->controller->findSettingsFiles();
|
||||
$this->layouts->assign('files', $files);
|
||||
return $this->layouts->get('components/settings/overview');
|
||||
//$content = $this->controller->populateDashboard();
|
||||
//$this->layouts->assign('content', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public function view()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public function modify()
|
||||
#[HiddenAttribute, DashboardAttribute("Hello!")]
|
||||
public function test()
|
||||
{
|
||||
|
||||
}
|
124
views/main/view.admin.settings.php
Executable file
124
views/main/view.admin.settings.php
Executable file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* FuzeWorks Framework Administration Plugin.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2020 i15
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author i15
|
||||
* @copyright Copyright (c) 2013 - 2020, i15. (https://i15.nl)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @since Version 1.3.0
|
||||
*
|
||||
* @version Version 1.3.0
|
||||
*/
|
||||
|
||||
namespace Application\View;
|
||||
use Application\Controller\SettingsController;
|
||||
use FuzeWorks\Administration\AdminView;
|
||||
use FuzeWorks\Administration\Attributes\DisplayAttribute;
|
||||
use FuzeWorks\Administration\Attributes\HiddenAttribute;
|
||||
use FuzeWorks\Administration\Attributes\IconAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PermissionAttribute;
|
||||
use FuzeWorks\Administration\Attributes\PriorityAttribute;
|
||||
use FuzeWorks\Controller;
|
||||
use FuzeWorks\Exception\NotFoundException;
|
||||
use FuzeWorks\Forms\Fields\CheckboxField;
|
||||
use FuzeWorks\Forms\Fields\TextField;
|
||||
use FuzeWorks\Forms\Forms;
|
||||
use FuzeWorks\Priority;
|
||||
|
||||
class SettingsAdminView extends AdminView
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SettingsController
|
||||
*/
|
||||
protected Controller $controller;
|
||||
|
||||
/**
|
||||
* Displays a list of settings files
|
||||
*/
|
||||
#[DisplayAttribute("Config"), IconAttribute("cog"), PriorityAttribute(Priority::LOWEST)]
|
||||
#[PermissionAttribute(["SUPER"])]
|
||||
public function index()
|
||||
{
|
||||
$files = $this->controller->findSettingsFiles();
|
||||
$this->layouts->assign('files', $files);
|
||||
return $this->layouts->get('components/settings/overview');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
#[HiddenAttribute, DisplayAttribute("View config file")]
|
||||
#[PermissionAttribute(["SUPER"])]
|
||||
public function view(string $request)
|
||||
{
|
||||
// Determine parts
|
||||
$parts = explode("/", $request);
|
||||
$file = $parts[0];
|
||||
$selector = intval($parts[1]);
|
||||
|
||||
// Select the file
|
||||
$data = $this->controller->fetchFile($file, $selector);
|
||||
|
||||
// Create a form out of the data
|
||||
/** @var Forms $forms */
|
||||
$forms = $this->libraries->get("forms");
|
||||
$form = $forms->getForm("ConfigEdit");
|
||||
foreach ($data['data'] as $key => $value)
|
||||
{
|
||||
switch (gettype($value))
|
||||
{
|
||||
case "string":
|
||||
case "integer":
|
||||
$field = new TextField($key);
|
||||
$field->setLabel($key)->setValue($value)->lock();
|
||||
$form->field($field);
|
||||
break;
|
||||
case "boolean":
|
||||
$field = new CheckboxField($key);
|
||||
$field->setLabel($key)->setValue($value)->lock();
|
||||
$form->field($field);
|
||||
break;
|
||||
default:
|
||||
dump(gettype($value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign and load layout
|
||||
$this->layouts->assign('config', $data);
|
||||
$this->layouts->assign('form', $form);
|
||||
return $this->layouts->get('components/settings/view');
|
||||
}
|
||||
|
||||
#[HiddenAttribute, DisplayAttribute("Edit config file")]
|
||||
#[PermissionAttribute(["SUPER"])]
|
||||
public function modify()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
0
www/.htaccess
Normal file → Executable file
0
www/.htaccess
Normal file → Executable file
29
www/dist/async.ts
vendored
Normal file
29
www/dist/async.ts
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
class AsyncManager {
|
||||
protected readonly url: string = "/admin/async";
|
||||
|
||||
constructor(url?: string) {
|
||||
if (url !== undefined)
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public getTaskList(onSuccess: Function, onError?: Function): void {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", this.url + ".json", true);
|
||||
xhr.send();
|
||||
// @todo Continue
|
||||
}
|
||||
}
|
||||
|
||||
let async: AsyncManager = new AsyncManager();
|
||||
|
||||
const url = "/admin/async";
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", url + ".json", true);
|
||||
xhr.send();
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200) {
|
||||
|
||||
}
|
||||
}
|
||||
|
0
www/index.php
Normal file → Executable file
0
www/index.php
Normal file → Executable file
Loading…
Reference in New Issue
Block a user