230 lines
8.2 KiB
PHP
230 lines
8.2 KiB
PHP
<?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 FuzeWorks\Administration;
|
|
use FuzeWorks\Administration\Events\AdminGenerateSidebarEvent;
|
|
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;
|
|
|
|
class PageFinder
|
|
{
|
|
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function generateSidebar(): array
|
|
{
|
|
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.');
|
|
|
|
// Then sort all those views into methods in the sidebar
|
|
$sorted = $this->sort($viewFileList);
|
|
|
|
// Log the result and return
|
|
Logger::log("Found " . count($sorted) . ' entries for sidebar.');
|
|
return $sorted;
|
|
}
|
|
|
|
/**
|
|
* Parse over every view component path and find all admin views.
|
|
*
|
|
* Return a file list.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function findViews(): array
|
|
{
|
|
/** @var Views $views */
|
|
$views = Factory::getInstance('views');
|
|
|
|
// First collect all the known paths
|
|
$paths = [];
|
|
for ($i = Priority::getHighestPriority(); $i<=Priority::getLowestPriority(); $i++)
|
|
$paths[$i] = $views->getComponentPaths($i);
|
|
|
|
// Then go over every individual paths
|
|
$viewFiles = [];
|
|
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)
|
|
{
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $viewFiles;
|
|
}
|
|
|
|
protected function sort(array $viewFileList): array
|
|
{
|
|
// Reflection docblock factory
|
|
$factory = DocBlockFactory::createInstance();
|
|
|
|
// Start sorting all methods
|
|
$entries = [];
|
|
foreach ($viewFileList as $viewId => $viewFile)
|
|
{
|
|
// 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);
|
|
} 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')
|
|
continue;
|
|
|
|
// Select all methods
|
|
$methods = $reflector->getMethods(ReflectionMethod::IS_PUBLIC);
|
|
|
|
// And pass over all of them
|
|
foreach ($methods as $method) {
|
|
// Prepare the entry output
|
|
$entry = [
|
|
'url' => ($id !== 'index' ? $id : '') . ($method->getName() !== 'index' ? '/' . $method->getName() : ''),
|
|
'priority' => Priority::NORMAL,
|
|
'display' => $reflector->getShortName() . '/' . $method->getName(),
|
|
'icon' => 'round'
|
|
];
|
|
|
|
// Only allow the methods in the actual class. Not from the parent method.
|
|
if ($method->class !== $className)
|
|
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))
|
|
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))
|
|
{
|
|
$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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write to entries
|
|
$entries[] = $entry;
|
|
}
|
|
}
|
|
|
|
// And finally return those
|
|
return $entries;
|
|
}
|
|
|
|
} |