From ffea22974a22a62d6cb566228b9481bb7a12a964 Mon Sep 17 00:00:00 2001 From: Xiao Hu Tai Date: Fri, 27 Jul 2018 16:31:25 +0200 Subject: [PATCH 1/3] Add display names feature (requires opt-in via `enabledisplaynames` in config) Fixes #84 --- config/config.yml.dist | 7 +++++-- src/Config/Config.php | 32 ++++++++++++++++++++++++++++++++ src/Parser/Parser.php | 16 +++++++++++++++- src/Provider/APIProvider.php | 3 ++- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/config/config.yml.dist b/config/config.yml.dist index 2d4d684..976f8f9 100644 --- a/config/config.yml.dist +++ b/config/config.yml.dist @@ -38,7 +38,7 @@ headers: replacements: 'src="//': 'src="http://' 'href="//': 'href="http://' - + # The base url where the API is accessible. base: '/json' @@ -52,4 +52,7 @@ date-iso-8601: true jsonoptions: 0 # Set this to true to disable frontend completely and display an empty page -disablefrontend: false \ No newline at end of file +disablefrontend: false + +# Adds a `ownerdisplayname` which has the record's ownerid's display name +enabledisplaynames: false diff --git a/src/Config/Config.php b/src/Config/Config.php index c727ad8..aa58cd6 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -67,6 +67,15 @@ class Config */ private $disableFrontend; + /** + * @var boolean + */ + private $enableDisplayNames; + + /** + * @param array $config + * @param Application $app + */ public function __construct($config, Application $app) { if (isset($config['base'])) { @@ -85,6 +94,9 @@ public function __construct($config, Application $app) $disablefrontend = isset($config['disablefrontend']) ? $config['disablefrontend'] : false; $this->setDisableFrontend($disablefrontend); + + $enableDisplayNames = isset($config['enabledisplaynames']) ? $config['enabledisplaynames'] : false; + $this->setEnableDisplayNames($enableDisplayNames); } /** @@ -350,4 +362,24 @@ public function setDisableFrontend($disableFrontend) return $this; } + + /** + * @return bool + */ + public function isEnableDisplayNames() + { + return $this->enableDisplayNames; + } + + /** + * @param bool $enableDisplayNames + * + * @return Config + */ + public function setEnableDisplayNames($enableDisplayNames) + { + $this->enableDisplayNames = $enableDisplayNames; + + return $this; + } } diff --git a/src/Parser/Parser.php b/src/Parser/Parser.php index 8234930..84e5cd0 100644 --- a/src/Parser/Parser.php +++ b/src/Parser/Parser.php @@ -9,6 +9,7 @@ use Bolt\Extension\Bolt\JsonApi\Parser\Field\FieldFactory; use Bolt\Storage\Entity\Relations; use Bolt\Storage\Mapping\MetadataDriver; +use Bolt\Users; class Parser { @@ -21,11 +22,15 @@ class Parser /** @var MetadataDriver $metadata */ protected $metadata; - public function __construct(Config $config, ResourceManager $resourceManager, MetadataDriver $metadata) + /** @var Users $users */ + protected $users; + + public function __construct(Config $config, ResourceManager $resourceManager, MetadataDriver $metadata, Users $users) { $this->config = $config; $this->resourceManager = $resourceManager; $this->metadata = $metadata; + $this->users = $users; } public function parseItem($item, $fields = []) @@ -90,6 +95,15 @@ public function parseItem($item, $fields = []) $values['attributes'] = $attributes; } + if ($this->config->isEnableDisplayNames() && isset($values['attributes']['ownerid'])) { + $ownerid = $values['attributes']['ownerid']; + $owner = $this->users->getUser($ownerid); + + if ($owner) { + $values['attributes']['ownerdisplayname'] = $owner['displayname']; + } + } + $values['links'] = [ 'self' => sprintf('%s/%s/%s', $this->config->getBasePath(), $contentType, $id), ]; diff --git a/src/Provider/APIProvider.php b/src/Provider/APIProvider.php index 5614c99..e2349b5 100644 --- a/src/Provider/APIProvider.php +++ b/src/Provider/APIProvider.php @@ -84,7 +84,8 @@ function ($app) { return new Parser( $app['jsonapi.config'], $app['resources'], - $app['storage.metadata'] + $app['storage.metadata'], + $app['users'] ); } ); From f020dba1e69c87709af120252f75b14d6e718621 Mon Sep 17 00:00:00 2001 From: Xiao Hu Tai Date: Fri, 27 Jul 2018 17:29:04 +0200 Subject: [PATCH 2/3] Rewrite menu responses [BREAKING CHANGE] --- src/Action/MenuAction.php | 82 ++++++++++++++++++++++++++++++------ src/Provider/APIProvider.php | 3 +- 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/Action/MenuAction.php b/src/Action/MenuAction.php index eaf0356..75e52e0 100644 --- a/src/Action/MenuAction.php +++ b/src/Action/MenuAction.php @@ -2,8 +2,10 @@ namespace Bolt\Extension\Bolt\JsonApi\Action; -use Bolt\Config; +use Bolt\Config as BoltConfig; +use Bolt\Extension\Bolt\JsonApi\Config\Config; use Bolt\Extension\Bolt\JsonApi\Exception\ApiNotFoundException; +use Bolt\Extension\Bolt\JsonApi\Helpers\DataLinks; use Bolt\Extension\Bolt\JsonApi\Response\ApiResponse; use Symfony\Component\HttpFoundation\Request; @@ -14,22 +16,27 @@ */ class MenuAction { - /** @var Config $config */ + /** @var BoltConfig $config */ protected $boltConfig; - /** @var \Bolt\Extension\Bolt\JsonApi\Config\Config $extensionConfig */ + /** @var Config $extensionConfig */ protected $extensionConfig; + /** @var DataLinks $dataLinks */ + protected $dataLinks; + /** * MenuAction constructor. * - * @param Config $boltConfig - * @param \Bolt\Extension\Bolt\JsonApi\Config\Config $extensionConfig + * @param BoltConfig $boltConfig + * @param Config $extensionConfig + * @param DataLinks $dataLinks */ - public function __construct(Config $boltConfig, \Bolt\Extension\Bolt\JsonApi\Config\Config $extensionConfig) + public function __construct(BoltConfig $boltConfig, Config $extensionConfig, DataLinks $dataLinks) { $this->boltConfig = $boltConfig; $this->extensionConfig = $extensionConfig; + $this->dataLinks = $dataLinks; } /** @@ -40,19 +47,70 @@ public function __construct(Config $boltConfig, \Bolt\Extension\Bolt\JsonApi\Con public function handle(Request $request) { if ($name = $request->get('q', '')) { - $name = "/$name"; + $data = $this->singleMenu($name); + } else { + $data = $this->allMenus(); } - $menu = $this->boltConfig->get('menu' . $name, false); - + return new ApiResponse([ + 'links' => [ + 'self' => $this->extensionConfig->getBasePath() . + "/menu" . + $this->dataLinks->makeQueryParameters($request->query->all()) + ], + 'data' => $data, + ], $this->extensionConfig); + } + + /** + * @param string $name + * + * @return array + */ + private function singleMenu($name) + { + $menu = $this->boltConfig->get('menu/' . $name, false); + if (! $menu) { throw new ApiNotFoundException( "Menu with name [$name] not found." ); } - return new ApiResponse([ - 'data' => $menu, - ], $this->extensionConfig); + return $this->parseMenu($name, $menu); + } + + /** + * @return array + */ + private function allMenus() + { + $menus = $this->boltConfig->get('menu', false); + + return array_map( + [$this, 'parseMenu'], + array_keys($menus), + array_values($menus) + ); + } + + /** + * @param string $name + * @param array $menu + * + * @return array + */ + private function parseMenu($name, $menu) + { + return [ + 'id' => $name, + 'type' => 'menu', + 'attributes' => [ + 'items' => $menu, + ], + 'links' => [ + 'self' => $this->extensionConfig->getBasePath() . "/menu?q=" . $name + ] + ]; } } diff --git a/src/Provider/APIProvider.php b/src/Provider/APIProvider.php index e2349b5..facd5c4 100644 --- a/src/Provider/APIProvider.php +++ b/src/Provider/APIProvider.php @@ -141,7 +141,8 @@ function ($app) { function ($app) { return new MenuAction( $app['config'], - $app['jsonapi.config'] + $app['jsonapi.config'], + $app['jsonapi.datalinks'] ); } ); From cc70902808015ffc8d9bd848457ca90fa83ff0b1 Mon Sep 17 00:00:00 2001 From: Xiao Hu Tai Date: Mon, 30 Jul 2018 13:00:47 +0200 Subject: [PATCH 3/3] Add `/menu/{q}` as alternative --- readme.md | 20 ++++++++++---------- src/Action/MenuAction.php | 5 ++++- src/Controllers/ContentController.php | 3 +++ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/readme.md b/readme.md index 082028e..e44e17e 100644 --- a/readme.md +++ b/readme.md @@ -62,7 +62,7 @@ contenttypes: allowed-fields: [ title, slug, teaser, image ] where-clause: status: 'published' - order: title,-datepublish + order: title,-datepublish pages: # use 'default' settings ``` @@ -129,14 +129,14 @@ parameters appended to the URL): Besides the basic JSON API features, below are some additional Bolt specific queries that you may find useful: -| URL | Description | -|-------------------------|-------------------------------------------------------------| -|`/{ct}/search?q={query}` | Searches for `{query}` in a specific `contenttype`. | -|`/search?q={query}` | Searches for `{query}` in all contenttypes. | -|`/menu` | Returns a list of all menus defined in `menu.yml`. | -|`/menu?q={name}` | Returns the menu with the specified name. | -|`/taxonomy` | Returns a list of all taxonomies defined in `taxonomy.yml`. | -|`/taxonomy?q={name}` | Returns the taxonomy with the specified name. | +| URL | Description | +|---------------------------------------|-------------------------------------------------------------| +|`/{ct}/search?q={query}` | Searches for `{query}` in a specific `contenttype`. | +|`/search?q={query}` | Searches for `{query}` in all contenttypes. | +|`/menu` | Returns a list of all menus defined in `menu.yml`. | +|`/menu?q={name}` or `/menu/{name}` | Returns the menu with the specified name. | +|`/taxonomy` | Returns a list of all taxonomies defined in `taxonomy.yml`. | +|`/taxonomy?q={name}` or `/menu/{name}` | Returns the taxonomy with the specified name. | ### Road Map @@ -151,4 +151,4 @@ queries that you may find useful: * Handle select-contenttype fields. * Add hooks for handling specific fieldtypes. * Add i18n for `detail` field in error messages. - * Add integration/hooks with other extensions, such as [`RelatedContentByTags`](https://github.com/xiaohutai/bolt-relatedcontentbytags). + * Add integration/hooks with other extensions. diff --git a/src/Action/MenuAction.php b/src/Action/MenuAction.php index 75e52e0..6d5fe36 100644 --- a/src/Action/MenuAction.php +++ b/src/Action/MenuAction.php @@ -46,8 +46,10 @@ public function __construct(BoltConfig $boltConfig, Config $extensionConfig, Dat */ public function handle(Request $request) { + $singleMenu = ''; if ($name = $request->get('q', '')) { $data = $this->singleMenu($name); + $singleMenu = "/$name"; } else { $data = $this->allMenus(); } @@ -56,6 +58,7 @@ public function handle(Request $request) 'links' => [ 'self' => $this->extensionConfig->getBasePath() . "/menu" . + $singleMenu . $this->dataLinks->makeQueryParameters($request->query->all()) ], 'data' => $data, @@ -109,7 +112,7 @@ private function parseMenu($name, $menu) 'items' => $menu, ], 'links' => [ - 'self' => $this->extensionConfig->getBasePath() . "/menu?q=" . $name + 'self' => $this->extensionConfig->getBasePath() . "/menu/" . $name ] ]; } diff --git a/src/Controllers/ContentController.php b/src/Controllers/ContentController.php index 0cb5182..ff2127c 100644 --- a/src/Controllers/ContentController.php +++ b/src/Controllers/ContentController.php @@ -50,6 +50,9 @@ public function connect(Application $app) $ctr->get('/menu', [$this, 'menu']) ->bind('jsonapi.menu'); + $ctr->get('/menu/{q}', [$this, 'menu']) + ->bind('jsonapi.singleMenu'); + $ctr->get('/taxonomy', [$this, 'taxonomy']) ->bind('jsonapi.taxonomy');