This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
drupalcampbristol/vendor/chi-teck/drupal-code-generator/templates/d8/plugin/rest-resource.twig

307 lines
8.4 KiB
Twig
Raw Normal View History

2018-11-23 12:29:20 +00:00
<?php
namespace Drupal\{{ machine_name }}\Plugin\rest\resource;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Database\Connection;
use Drupal\rest\ModifiedResourceResponse;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Represents {{ plugin_label }} records as resources.
*
* @RestResource (
* id = "{{ plugin_id }}",
* label = @Translation("{{ plugin_label }}"),
* uri_paths = {
* "canonical" = "/api/{{ plugin_id|u2h }}/{id}",
* "https://www.drupal.org/link-relations/create" = "/api/{{ plugin_id|u2h }}"
* }
* )
*
* @DCG
* This plugin exposes database records as REST resources. In order to enable it
* import the resource configuration into active configuration storage. You may
* find an example of such configuration in the following file:
* core/modules/rest/config/optional/rest.resource.entity.node.yml.
* Alternatively you can make use of REST UI module.
* @see https://www.drupal.org/project/restui
* For accessing Drupal entities through REST interface use
* \Drupal\rest\Plugin\rest\resource\EntityResource plugin.
*/
class {{ class }} extends ResourceBase implements DependentPluginInterface {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $dbConnection;
/**
* Constructs a Drupal\rest\Plugin\rest\resource\EntityResource object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param array $serializer_formats
* The available serialization formats.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
* @param \Drupal\Core\Database\Connection $db_connection
* The database connection.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, Connection $db_connection) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
$this->dbConnection = $db_connection;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->getParameter('serializer.formats'),
$container->get('logger.factory')->get('rest'),
$container->get('database')
);
}
/**
* Responds to GET requests.
*
* @param int $id
* The ID of the record.
*
* @return \Drupal\rest\ResourceResponse
* The response containing the record.
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function get($id) {
return new ResourceResponse($this->loadRecord($id));
}
/**
* Responds to POST requests and saves the new record.
*
* @param mixed $record
* Data to write into the database.
*
* @return \Drupal\rest\ModifiedResourceResponse
* The HTTP response object.
*/
public function post($record) {
$this->validate($record);
$id = $this->dbConnection->insert('{{ plugin_id }}')
->fields($record)
->execute();
$this->logger->notice('New {{ plugin_label|lower }} record has been created.');
$created_record = $this->loadRecord($id);
// Return the newly created record in the response body.
return new ModifiedResourceResponse($created_record, 201);
}
/**
* Responds to entity PATCH requests.
*
* @param int $id
* The ID of the record.
* @param mixed $record
* Data to write into the database.
*
* @return \Drupal\rest\ModifiedResourceResponse
* The HTTP response object.
*/
public function patch($id, $record) {
$this->validate($record);
return $this->updateRecord($id, $record);
}
/**
* Responds to entity PUT requests.
*
* @param int $id
* The ID of the record.
* @param mixed $record
* Data to write into the database.
*
* @return \Drupal\rest\ModifiedResourceResponse
* The HTTP response object.
*/
public function put($id, $record) {
$this->validate($record);
// Provide default values to make sure the record is completely replaced.
$record += [
'title' => '',
'description' => '',
'price' => 0,
];
return $this->updateRecord($id, $record);
}
/**
* Responds to entity DELETE requests.
*
* @param int $id
* The ID of the record.
*
* @return \Drupal\rest\ModifiedResourceResponse
* The HTTP response object.
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function delete($id) {
// Make sure the record still exists.
$this->loadRecord($id);
$this->dbConnection->delete('{{ plugin_id }}')
->condition('id', $id)
->execute();
$this->logger->notice('{{ plugin_label }} record @id has been deleted.', ['@id' => $id]);
// Deleted responses have an empty body.
return new ModifiedResourceResponse(NULL, 204);
}
/**
* {@inheritdoc}
*/
protected function getBaseRoute($canonical_path, $method) {
$route = parent::getBaseRoute($canonical_path, $method);
// Change ID validation pattern.
if ($method != 'POST') {
$route->setRequirement('id', '\d+');
}
return $route;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
return [];
}
/**
* {@inheritdoc}
*/
public function routes() {
$collection = parent::routes();
// ResourceBase class does not support PUT method by some reason.
$definition = $this->getPluginDefinition();
$canonical_path = $definition['uri_paths']['canonical'];
$route = $this->getBaseRoute($canonical_path, 'PUT');
$route->addRequirements(['_content_type_format' => implode('|', $this->serializerFormats)]);
$collection->add('{{ plugin_id }}.PUT', $route);
return $collection;
}
/**
* Validates incoming record.
*
* @param mixed $record
* Data to validate.
*
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
*/
protected function validate($record) {
if (!is_array($record) || count($record) == 0) {
throw new BadRequestHttpException('No record content received.');
}
$allowed_fields = [
'title',
'description',
'price',
];
if (count(array_diff(array_keys($record), $allowed_fields)) > 0) {
throw new BadRequestHttpException('Record structure is not correct.');
}
if (empty($record['title'])) {
throw new BadRequestHttpException('Title is required.');
}
elseif (isset($record['title']) && strlen($record['title']) > 255) {
throw new BadRequestHttpException('Title is too big.');
}
// @DCG Add more validation rules here.
}
/**
* Loads record from database.
*
* @param int $id
* The ID of the record.
*
* @return array
* The database record.
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
*/
protected function loadRecord($id) {
$record = $this->dbConnection->query('SELECT * FROM {{ '{' }}{{ plugin_id }}{{ '}' }} WHERE id = :id', [':id' => $id])->fetchAssoc();
if (!$record) {
throw new NotFoundHttpException('The record was not found.');
}
return $record;
}
/**
* Updates record.
*
* @param int $id
* The ID of the record.
* @param array $record
* The record to validate.
*
* @return \Drupal\rest\ModifiedResourceResponse
* The HTTP response object.
*/
protected function updateRecord($id, array $record) {
// Make sure the record already exists.
$this->loadRecord($id);
$this->validate($record);
$this->dbConnection->update('{{ plugin_id }}')
->fields($record)
->condition('id', $id)
->execute();
$this->logger->notice('{{ plugin_label }} record @id has been updated.', ['@id' => $id]);
// Return the updated record in the response body.
$updated_record = $this->loadRecord($id);
return new ModifiedResourceResponse($updated_record, 200);
}
}