session = $session; Logger::log("Generating sidebar..."); $event = Events::fireEvent('adminGenerateSidebarEvent'); if ($event->isCancelled()) return []; // First find all views $views = $this->findViews(); Logger::log("Found " . count($views) . ' admin views.'); // Then sort all those views into methods in the sidebar $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 string[] */ 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 $views = []; 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 (!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 $views; } /** * 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 { $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 ($views as $view) { // Try and reflect on this class. try { $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 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); // 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 !== $view) continue; // Read attributes // First read hidden attribute. If present, skip this method $hiddenAttributes = $method->getAttributes(HiddenAttribute::class); if (!empty($hiddenAttributes)) continue; // Then check for permissions $permissionAttributes = $method->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) 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['priority']][] = $entry; } } // 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; } }