123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- <?php
- declare(strict_types=1);
- namespace Grav\Plugin\FlexObjects;
- use Grav\Common\Config\Config;
- use Grav\Common\Filesystem\Folder;
- use Grav\Common\Grav;
- use Grav\Common\Page\Interfaces\PageInterface;
- use Grav\Common\Utils;
- use Grav\Framework\Flex\FlexDirectory;
- use Grav\Framework\Flex\FlexObject;
- use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
- use Grav\Framework\Flex\Interfaces\FlexCommonInterface;
- use Grav\Framework\Flex\Interfaces\FlexDirectoryInterface;
- use Grav\Framework\Flex\Interfaces\FlexInterface;
- use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
- use Grav\Plugin\FlexObjects\Admin\AdminController;
- use Grav\Plugin\FlexObjects\Table\DataTable;
- /**
- * Class Flex
- * @package Grav\Plugin\FlexObjects
- */
- class Flex implements FlexInterface
- {
- /** @var FlexInterface */
- protected $flex;
- /** @var array */
- protected $adminRoutes;
- /** @var array */
- protected $adminMenu;
- /** @var array */
- protected $managed;
- /**
- * @param bool $newToOld
- * @return array
- * @internal
- */
- public static function getLegacyBlueprintMap(bool $newToOld = true): array
- {
- $map = [
- 'blueprints://flex-objects/pages.yaml' => 'blueprints://flex-objects/grav-pages.yaml',
- 'blueprints://flex-objects/user-accounts.yaml' => 'blueprints://flex-objects/grav-accounts.yaml',
- 'blueprints://flex-objects/user-groups.yaml' => 'blueprints://flex-objects/grav-user-groups.yaml'
- ];
- return $newToOld ? $map : array_flip($map);
- }
- /**
- * Flex constructor.
- * @param FlexInterface $flex
- * @param array $types
- */
- public function __construct(FlexInterface $flex, array $types)
- {
- $this->flex = $flex;
- $this->managed = [];
- $legacy = static::getLegacyBlueprintMap(false);
- foreach ($types as $blueprint) {
- // Backwards compatibility to v1.0.0-rc.3
- $blueprint = $legacy[$blueprint] ?? $blueprint;
- $type = Utils::basename((string)$blueprint, '.yaml');
- if ($type) {
- $this->managed[] = $type;
- }
- }
- }
- /**
- * @param string $type
- * @param string $blueprint
- * @param array $config
- * @return $this
- */
- public function addDirectoryType(string $type, string $blueprint, array $config = [])
- {
- $this->flex->addDirectoryType($type, $blueprint, $config);
- return $this;
- }
- /**
- * @param FlexDirectory $directory
- * @return $this
- */
- public function addDirectory(FlexDirectory $directory)
- {
- $this->flex->addDirectory($directory);
- return $this;
- }
- /**
- * @param string $type
- * @return bool
- */
- public function hasDirectory(string $type): bool
- {
- return $this->flex->hasDirectory($type);
- }
- /**
- * @param string[]|null $types
- * @param bool $keepMissing
- * @return array<FlexDirectoryInterface|null>
- */
- public function getDirectories(array $types = null, bool $keepMissing = false): array
- {
- return $this->flex->getDirectories($types, $keepMissing);
- }
- /**
- * Get directories which are not hidden in the site.
- *
- * @return array
- */
- public function getDefaultDirectories(): array
- {
- $list = $this->getDirectories();
- foreach ($list as $type => $directory) {
- if ($directory->getConfig('site.hidden', false)) {
- unset($list[$type]);
- }
- }
- return $list;
- }
- /**
- * @param string $type
- * @return FlexDirectory|null
- */
- public function getDirectory(string $type): ?FlexDirectory
- {
- return $this->flex->getDirectory($type);
- }
- /**
- * @param string $type
- * @param array|null $keys
- * @param string|null $keyField
- * @return FlexCollectionInterface|null
- */
- public function getCollection(string $type, array $keys = null, string $keyField = null): ?FlexCollectionInterface
- {
- return $this->flex->getCollection($type, $keys, $keyField);
- }
- /**
- * @param array $keys
- * @param array $options In addition to the options in getObjects(), following options can be passed:
- * collection_class: Class to be used to create the collection. Defaults to ObjectCollection.
- * @return FlexCollectionInterface
- * @throws \RuntimeException
- */
- public function getMixedCollection(array $keys, array $options = []): FlexCollectionInterface
- {
- return $this->flex->getMixedCollection($keys, $options);
- }
- /**
- * @param array $keys
- * @param array $options Following optional options can be passed:
- * types: List of allowed types.
- * type: Allowed type if types isn't defined, otherwise acts as default_type.
- * default_type: Set default type for objects given without type (only used if key_field isn't set).
- * keep_missing: Set to true if you want to return missing objects as null.
- * key_field: Key field which is used to match the objects.
- * @return array
- */
- public function getObjects(array $keys, array $options = []): array
- {
- return $this->flex->getObjects($keys, $options);
- }
- /**
- * @param string $key
- * @param string|null $type
- * @param string|null $keyField
- * @return FlexObjectInterface|null
- */
- public function getObject(string $key, string $type = null, string $keyField = null): ?FlexObjectInterface
- {
- return $this->flex->getObject($key, $type, $keyField);
- }
- /**
- * @return int
- */
- public function count(): int
- {
- return $this->flex->count();
- }
- public function isManaged(string $type): bool
- {
- return \in_array($type, $this->managed, true);
- }
- /**
- * @return array
- */
- public function getAll(): array
- {
- $directories = $this->getDirectories($this->managed);
- $all = $this->getBlueprints();
- /** @var FlexDirectory $directory */
- foreach ($all as $type => $directory) {
- if (!isset($directories[$type])) {
- $directories[$type] = $directory;
- }
- }
- ksort($directories);
- return $directories;
- }
- /**
- * @return array
- */
- public function getBlueprints(): array
- {
- $params = [
- 'pattern' => '|\.yaml|',
- 'value' => 'Url',
- 'recursive' => false,
- 'folders' => false
- ];
- $directories = [];
- $all = Folder::all('blueprints://flex-objects', $params);
- foreach ($all as $url) {
- $type = Utils::basename($url, '.yaml');
- $directory = new FlexDirectory($type, $url);
- if ($directory->getConfig('hidden') !== true) {
- $directories[$type] = $directory;
- }
- }
- // Order blueprints by title.
- usort($directories, static function (FlexDirectory $a, FlexDirectory $b) {
- return $a->getTitle() <=> $b->getTitle();
- });
- return $directories;
- }
- /**
- * @param string|FlexDirectory $type
- * @param array $options
- * @return DataTable
- */
- public function getDataTable($type, array $options = []): DataTable
- {
- $directory = $type instanceof FlexDirectory ? $type : $this->getDirectory($type);
- if (!$directory) {
- throw new \RuntimeException('Not Found', 404);
- }
- $collection = $options['collection'] ?? $directory->getCollection();
- if (isset($options['filters']) && is_array($options['filters'])) {
- $collection = $collection->filterBy($options['filters']);
- }
- $table = new DataTable($options);
- $table->setCollection($collection);
- return $table;
- }
- /**
- * @param string|object|null $type
- * @param array $params
- * @param string $extension
- * @return string
- */
- public function adminRoute($type = null, array $params = [], string $extension = ''): string
- {
- if (\is_object($type)) {
- $object = $type;
- if ($object instanceof FlexCommonInterface || $object instanceof FlexDirectory) {
- $type = $type->getFlexType();
- } else {
- return '';
- }
- } else {
- $object = null;
- }
- $routes = $this->getAdminRoutes();
- $grav = Grav::instance();
- /** @var Config $config */
- $config = $grav['config'];
- if (!Utils::isAdminPlugin()) {
- $parts = [
- trim($grav['base_url'], '/'),
- trim($config->get('plugins.admin.route'), '/')
- ];
- }
- if ($type && isset($routes[$type])) {
- if (!$routes[$type]) {
- // Directory has empty route.
- return '';
- }
- // Directory has it's own menu item.
- $parts[] = trim($routes[$type], '/');
- } else {
- if (empty($routes[''])) {
- // Default route has been disabled.
- return '';
- }
- // Use default route.
- $parts[] = trim($routes[''], '/');
- if ($type) {
- $parts[] = $type;
- }
- }
- // Append object key if available.
- if ($object instanceof FlexObject) {
- if ($object->exists()) {
- $parts[] = trim($object->getKey(), '/');
- } else {
- if ($object->hasKey()) {
- $parts[] = trim($object->getKey(), '/');
- }
- $params = ['' => 'add'] + $params;
- }
- }
- $p = [];
- $separator = $config->get('system.param_sep');
- foreach ($params as $key => $val) {
- $p[] = $key . $separator . $val;
- }
- $parts = array_filter($parts, static function ($val) { return $val !== ''; });
- $route = '/' . implode('/', $parts);
- $extension = $extension ? '.' . $extension : '';
- return $route . $extension . ($p ? '/' . implode('/', $p) : '');
- }
- public function getAdminController(): ?AdminController
- {
- $grav = Grav::instance();
- if (!isset($grav['admin'])) {
- return null;
- }
- /** @var PageInterface $page */
- $page = $grav['page'];
- $header = $page->header();
- $callable = $header->controller['controller']['instance'] ?? null;
- if (null !== $callable && \is_callable($callable)) {
- return $callable();
- }
- return null;
- }
- /**
- * @return array
- */
- public function getAdminRoutes(): array
- {
- if (null === $this->adminRoutes) {
- $routes = [];
- /** @var FlexDirectory $directory */
- foreach ($this->getDirectories() as $directory) {
- $config = $directory->getConfig('admin');
- if (!$directory->isEnabled() || !empty($config['disabled'])) {
- continue;
- }
- // Resolve route.
- $route = $config['router']['path']
- ?? $config['menu']['list']['route']
- ?? "/flex-objects/{$directory->getFlexType()}";
- $routes[$directory->getFlexType()] = $route;
- }
- $this->adminRoutes = $routes;
- }
- return $this->adminRoutes;
- }
- /**
- * @return array
- */
- public function getAdminMenuItems(): array
- {
- if (null === $this->adminMenu) {
- $routes = [];
- $count = 0;
- $directories = $this->getDirectories();
- /** @var FlexDirectory $directory */
- foreach ($directories as $directory) {
- $config = $directory->getConfig('admin');
- if (!$directory->isEnabled() || !empty($config['disabled'])) {
- continue;
- }
- $type = $directory->getFlexType();
- $items = $directory->getConfig('admin.menu') ?? [];
- if ($items) {
- foreach ($items as $view => $item) {
- $item += [
- 'route' => '/' . $type,
- 'title' => $directory->getTitle(),
- 'icon' => 'fa fa-file',
- 'directory' => $type
- ];
- $routes[$type] = $item;
- }
- } else {
- $count++;
- }
- }
- if ($count && !isset($routes[''])) {
- $routes[''] = ['route' => '/flex-objects'];
- }
- $this->adminMenu = $routes;
- }
- return $this->adminMenu;
- }
- }
|