-
Notifications
You must be signed in to change notification settings - Fork 0
Add in cacheable json response #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
10ce674
286447c
c45dfe0
969550f
1bb116b
71eea13
c2ae081
efe7e4c
5497ede
72aee85
9092a43
aec5040
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| <?php | ||
|
|
||
| namespace Drupal\bc_api_example\Controller; | ||
|
|
||
| use Drupal\bc_api_base\Controller\ApiControllerBase; | ||
| use Drupal\bc_api_base\CacheableJsonResponseTrait; | ||
|
|
||
| /** | ||
| * Example API Controller Class. | ||
| * | ||
| * @ApiDoc( | ||
| * params = { | ||
| * @ApiParam( | ||
| * name = "status", | ||
| * type = "bool", | ||
| * description = "Filter on node status.", | ||
| * default = "TRUE", | ||
| * ), | ||
| * @ApiParam( | ||
| * name = "nat", | ||
| * type = "int", | ||
| * description = "Filter on nationality. This should use the taxonomy id of the nationality.", | ||
| * ), | ||
| * } | ||
| * ) | ||
| */ | ||
| class ApiControllerCacheableResponsePirateExample extends ApiControllerBase { | ||
|
|
||
| use CacheableJsonResponseTrait; | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function getApiCacheTime($id = NULL) { | ||
| // Parent method looks at settings form and takes into account list or | ||
| // detail. | ||
| return 0; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function getCacheId() { | ||
| // This should be a unique string, characters only. | ||
| $cid = "yo-ho-ho"; | ||
|
|
||
| if (!empty($this->params)) { | ||
| $cid .= ":" . implode(":", $this->params); | ||
| } | ||
|
|
||
| $cid .= ":page-" . $this->page; | ||
| $cid .= ":limit-" . $this->limit; | ||
|
|
||
| return $cid; | ||
pingevt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function initCacheTags() { | ||
| $this->cacheTags = [ | ||
| 'myAwesomeCoolCacheTag', | ||
| ]; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function setParams() { | ||
| // It would be good to always run this. | ||
| parent::setParams(); | ||
|
|
||
| $this->privateParams['status'] = 1; | ||
|
|
||
| // Here we also want to handle any bad param errors... | ||
pingevt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function getDefaultPlatform() { | ||
| return "cinder"; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function getResourceQueryResult() { | ||
| // Just having this here as an example. | ||
| // Most times no need to override this method. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused by this comment, because lines 92-94 show a clear reason for overriding the method.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm... ok the non-cacheable one makes sense. But this one doesn't. Esp. since I'm using a trait and not extending the class. 🤔
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well... that "example" should be added to the trait. then the comment will be valid then. |
||
| parent::getResourceQueryResult(); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function getResourceListQueryResult() { | ||
| // This method should be overridden for any endpoint. | ||
| $query = $this->entityTypeManager->getStorage('node')->getQuery(); | ||
| $query->accessCheck(TRUE); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i know this is just an example, but should we recommend that |
||
| $query->condition('status', $this->privateParams['status']); | ||
| $query->condition('type', 'pirate'); | ||
|
|
||
| $count_query = clone $query; | ||
|
|
||
| $query->range(($this->page * $this->limit), $this->limit); | ||
| $entity_ids = $query->execute(); | ||
|
|
||
| // Must set total result count so we can properly page. | ||
| $this->resultTotal = (int) $count_query->count()->execute(); | ||
|
|
||
| // Process Items. | ||
| $nodes = $this->entityTypeManager->getStorage('node')->loadMultiple($entity_ids); | ||
|
|
||
| $this->rawData = $nodes; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function buildAllResourceData() { | ||
| $data = []; | ||
|
|
||
| foreach ($this->rawData as $node) { | ||
| $this->cacheTags = array_merge($this->cacheTags, $node->getCacheTags()); | ||
pingevt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| $this->addCacheableDependency($node); | ||
| $created_changed = $this->transformer->createdChangedFieldVals($node); | ||
|
|
||
| $item = [ | ||
| 'nid' => (int) $node->id(), | ||
| 'cms_title' => $node->label(), | ||
| 'created' => $created_changed[0], | ||
| 'updated' => $created_changed[1], | ||
| ]; | ||
| $data[] = $item; | ||
| } | ||
|
|
||
| $this->data = $data; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function buildLinks() { | ||
| // This method should be overridden for any endpoint. | ||
| $base_url = $this->request->getSchemeAndHttpHost() . $this->request->getPathInfo(); | ||
| $tmp_query_params = $this->params; | ||
| $tmp_query_params['platform'] = $this->platform; | ||
| $tmp_query_params['limit'] = $this->limit; | ||
|
|
||
| if ($this->page == 0) { | ||
| $this->prev = ""; | ||
| } | ||
| else { | ||
| $tmp_query_params['page'] = $this->page - 1; | ||
| $this->prev = $base_url . "?" . http_build_query($tmp_query_params); | ||
| } | ||
|
|
||
| if ($this->resultTotal > (($this->page + 1) * $this->limit)) { | ||
| $tmp_query_params['page'] = $this->page + 1; | ||
| $this->next = $base_url . "?" . http_build_query($tmp_query_params); | ||
| } | ||
| else { | ||
|
|
||
| $this->next = ""; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| <?php | ||
|
|
||
| namespace Drupal\bc_api_base; | ||
|
|
||
| use Drupal\Core\Cache\CacheableJsonResponse; | ||
| use Drupal\Core\Cache\CacheableMetadata; | ||
| use Symfony\Component\HttpFoundation\Response; | ||
|
|
||
| /** | ||
| * Trait CacheableJsonResponseTrait. | ||
| * | ||
| * This trait provides a way to create cacheable JSON responses. It allows for | ||
| * the addition of cacheable metadata and dependencies to the response, ensuring | ||
| * that the response can be cached appropriately. | ||
| */ | ||
| trait CacheableJsonResponseTrait { | ||
|
|
||
| /** | ||
| * Cacheable metadata for the response. | ||
| * | ||
| * @var \Drupal\Core\Cache\CacheableMetadata | ||
| */ | ||
| protected $cacheMetadata = NULL; | ||
|
|
||
| /** | ||
| * Returns the cacheable metadata for the response. | ||
| * | ||
| * When building any data, cacheable metadata should be set from there. And it | ||
| * will be applied when the request is altered. | ||
| * | ||
| * @return \Drupal\Core\Cache\CacheableMetadata | ||
| */ | ||
| protected function getCacheableMetadata(): CacheableMetadata { | ||
| if (!isset($this->cacheMetadata)) { | ||
| $this->cacheMetadata = new CacheableMetadata(); | ||
| } | ||
| return $this->cacheMetadata; | ||
| } | ||
|
|
||
| /** | ||
| * Adds a dependency on an object: merges its cacheability metadata. | ||
| * | ||
| * For instance, when a response depends on some configuration, an entity, or | ||
| * an access result, we must make sure their cacheability metadata is present | ||
| * on the response. This method makes doing that simple. | ||
| * | ||
| * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $dependency | ||
| * The dependency. If the object implements CacheableDependencyInterface, | ||
| * then its cacheability metadata will be used. Otherwise, the passed in | ||
| * object must be assumed to be uncacheable, so max-age 0 is set. | ||
| * | ||
| * @return $this | ||
| */ | ||
| public function addCacheableDependency($dependency) { | ||
|
|
||
| $this->cacheMetadata = $this->getCacheableMetadata()->merge(CacheableMetadata::createFromObject($dependency)); | ||
|
|
||
| return $this; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function getResourceQueryResult() { | ||
| parent::getResourceQueryResult(); | ||
|
|
||
| // If the resource is set, add it as a cacheable dependency. | ||
| if (isset($this->resource) && !empty($this->resource)) { | ||
| $this->addCacheableDependency($this->resource); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| * | ||
| * Override the base classes response, to create a cacheable response. | ||
| */ | ||
| public function createResponse(): Response { | ||
| $response = new CacheableJsonResponse($this->return_data); | ||
|
|
||
| // Attach cache metadata if available. | ||
| if ($cache_metadata = $this->getCacheableMetadata()) { | ||
| $response->addCacheableDependency($cache_metadata); | ||
| } | ||
|
|
||
| // Alter it. | ||
| $this->responseAlter($response); | ||
|
|
||
| return $response; | ||
| } | ||
|
|
||
| } |
Uh oh!
There was an error while loading. Please reload this page.