annotate vendor/chi-teck/drupal-code-generator/templates/d8/plugin/rest-resource.twig @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children a9cd425dd02b
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\{{ machine_name }}\Plugin\rest\resource;
Chris@0 4
Chris@0 5 use Drupal\Component\Plugin\DependentPluginInterface;
Chris@0 6 use Drupal\Core\Database\Connection;
Chris@0 7 use Drupal\rest\ModifiedResourceResponse;
Chris@0 8 use Drupal\rest\Plugin\ResourceBase;
Chris@0 9 use Drupal\rest\ResourceResponse;
Chris@0 10 use Psr\Log\LoggerInterface;
Chris@0 11 use Symfony\Component\DependencyInjection\ContainerInterface;
Chris@0 12 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
Chris@0 13 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
Chris@0 14
Chris@0 15 /**
Chris@0 16 * Represents {{ plugin_label }} records as resources.
Chris@0 17 *
Chris@0 18 * @RestResource (
Chris@0 19 * id = "{{ plugin_id }}",
Chris@0 20 * label = @Translation("{{ plugin_label }}"),
Chris@0 21 * uri_paths = {
Chris@0 22 * "canonical" = "/api/{{ plugin_id|u2h }}/{id}",
Chris@0 23 * "https://www.drupal.org/link-relations/create" = "/api/{{ plugin_id|u2h }}"
Chris@0 24 * }
Chris@0 25 * )
Chris@0 26 *
Chris@0 27 * @DCG
Chris@0 28 * This plugin exposes database records as REST resources. In order to enable it
Chris@0 29 * import the resource configuration into active configuration storage. You may
Chris@0 30 * find an example of such configuration in the following file:
Chris@0 31 * core/modules/rest/config/optional/rest.resource.entity.node.yml.
Chris@0 32 * Alternatively you can make use of REST UI module.
Chris@0 33 * @see https://www.drupal.org/project/restui
Chris@0 34 * For accessing Drupal entities through REST interface use
Chris@0 35 * \Drupal\rest\Plugin\rest\resource\EntityResource plugin.
Chris@0 36 */
Chris@0 37 class {{ class }} extends ResourceBase implements DependentPluginInterface {
Chris@0 38
Chris@0 39 /**
Chris@0 40 * The database connection.
Chris@0 41 *
Chris@0 42 * @var \Drupal\Core\Database\Connection
Chris@0 43 */
Chris@0 44 protected $dbConnection;
Chris@0 45
Chris@0 46 /**
Chris@0 47 * Constructs a Drupal\rest\Plugin\rest\resource\EntityResource object.
Chris@0 48 *
Chris@0 49 * @param array $configuration
Chris@0 50 * A configuration array containing information about the plugin instance.
Chris@0 51 * @param string $plugin_id
Chris@0 52 * The plugin_id for the plugin instance.
Chris@0 53 * @param mixed $plugin_definition
Chris@0 54 * The plugin implementation definition.
Chris@0 55 * @param array $serializer_formats
Chris@0 56 * The available serialization formats.
Chris@0 57 * @param \Psr\Log\LoggerInterface $logger
Chris@0 58 * A logger instance.
Chris@0 59 * @param \Drupal\Core\Database\Connection $db_connection
Chris@0 60 * The database connection.
Chris@0 61 */
Chris@0 62 public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, Connection $db_connection) {
Chris@0 63 parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
Chris@0 64 $this->dbConnection = $db_connection;
Chris@0 65 }
Chris@0 66
Chris@0 67 /**
Chris@0 68 * {@inheritdoc}
Chris@0 69 */
Chris@0 70 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
Chris@0 71 return new static(
Chris@0 72 $configuration,
Chris@0 73 $plugin_id,
Chris@0 74 $plugin_definition,
Chris@0 75 $container->getParameter('serializer.formats'),
Chris@0 76 $container->get('logger.factory')->get('rest'),
Chris@0 77 $container->get('database')
Chris@0 78 );
Chris@0 79 }
Chris@0 80
Chris@0 81 /**
Chris@0 82 * Responds to GET requests.
Chris@0 83 *
Chris@0 84 * @param int $id
Chris@0 85 * The ID of the record.
Chris@0 86 *
Chris@0 87 * @return \Drupal\rest\ResourceResponse
Chris@0 88 * The response containing the record.
Chris@0 89 *
Chris@0 90 * @throws \Symfony\Component\HttpKernel\Exception\HttpException
Chris@0 91 */
Chris@0 92 public function get($id) {
Chris@0 93 return new ResourceResponse($this->loadRecord($id));
Chris@0 94 }
Chris@0 95
Chris@0 96 /**
Chris@0 97 * Responds to POST requests and saves the new record.
Chris@0 98 *
Chris@0 99 * @param mixed $record
Chris@0 100 * Data to write into the database.
Chris@0 101 *
Chris@0 102 * @return \Drupal\rest\ModifiedResourceResponse
Chris@0 103 * The HTTP response object.
Chris@0 104 */
Chris@0 105 public function post($record) {
Chris@0 106
Chris@0 107 $this->validate($record);
Chris@0 108
Chris@0 109 $id = $this->dbConnection->insert('{{ plugin_id }}')
Chris@0 110 ->fields($record)
Chris@0 111 ->execute();
Chris@0 112
Chris@0 113 $this->logger->notice('New {{ plugin_label|lower }} record has been created.');
Chris@0 114
Chris@0 115 $created_record = $this->loadRecord($id);
Chris@0 116
Chris@0 117 // Return the newly created record in the response body.
Chris@0 118 return new ModifiedResourceResponse($created_record, 201);
Chris@0 119 }
Chris@0 120
Chris@0 121 /**
Chris@0 122 * Responds to entity PATCH requests.
Chris@0 123 *
Chris@0 124 * @param int $id
Chris@0 125 * The ID of the record.
Chris@0 126 * @param mixed $record
Chris@0 127 * Data to write into the database.
Chris@0 128 *
Chris@0 129 * @return \Drupal\rest\ModifiedResourceResponse
Chris@0 130 * The HTTP response object.
Chris@0 131 */
Chris@0 132 public function patch($id, $record) {
Chris@0 133 $this->validate($record);
Chris@0 134 return $this->updateRecord($id, $record);
Chris@0 135 }
Chris@0 136
Chris@0 137 /**
Chris@0 138 * Responds to entity PUT requests.
Chris@0 139 *
Chris@0 140 * @param int $id
Chris@0 141 * The ID of the record.
Chris@0 142 * @param mixed $record
Chris@0 143 * Data to write into the database.
Chris@0 144 *
Chris@0 145 * @return \Drupal\rest\ModifiedResourceResponse
Chris@0 146 * The HTTP response object.
Chris@0 147 */
Chris@0 148 public function put($id, $record) {
Chris@0 149
Chris@0 150 $this->validate($record);
Chris@0 151
Chris@0 152 // Provide default values to make sure the record is completely replaced.
Chris@0 153 $record += [
Chris@0 154 'title' => '',
Chris@0 155 'description' => '',
Chris@0 156 'price' => 0,
Chris@0 157 ];
Chris@0 158
Chris@0 159 return $this->updateRecord($id, $record);
Chris@0 160 }
Chris@0 161
Chris@0 162 /**
Chris@0 163 * Responds to entity DELETE requests.
Chris@0 164 *
Chris@0 165 * @param int $id
Chris@0 166 * The ID of the record.
Chris@0 167 *
Chris@0 168 * @return \Drupal\rest\ModifiedResourceResponse
Chris@0 169 * The HTTP response object.
Chris@0 170 *
Chris@0 171 * @throws \Symfony\Component\HttpKernel\Exception\HttpException
Chris@0 172 */
Chris@0 173 public function delete($id) {
Chris@0 174
Chris@0 175 // Make sure the record still exists.
Chris@0 176 $this->loadRecord($id);
Chris@0 177
Chris@0 178 $this->dbConnection->delete('{{ plugin_id }}')
Chris@0 179 ->condition('id', $id)
Chris@0 180 ->execute();
Chris@0 181
Chris@0 182 $this->logger->notice('{{ plugin_label }} record @id has been deleted.', ['@id' => $id]);
Chris@0 183
Chris@0 184 // Deleted responses have an empty body.
Chris@0 185 return new ModifiedResourceResponse(NULL, 204);
Chris@0 186 }
Chris@0 187
Chris@0 188 /**
Chris@0 189 * {@inheritdoc}
Chris@0 190 */
Chris@0 191 protected function getBaseRoute($canonical_path, $method) {
Chris@0 192 $route = parent::getBaseRoute($canonical_path, $method);
Chris@0 193
Chris@0 194 // Change ID validation pattern.
Chris@0 195 if ($method != 'POST') {
Chris@0 196 $route->setRequirement('id', '\d+');
Chris@0 197 }
Chris@0 198
Chris@0 199 return $route;
Chris@0 200 }
Chris@0 201
Chris@0 202 /**
Chris@0 203 * {@inheritdoc}
Chris@0 204 */
Chris@0 205 public function calculateDependencies() {
Chris@0 206 return [];
Chris@0 207 }
Chris@0 208
Chris@0 209 /**
Chris@0 210 * {@inheritdoc}
Chris@0 211 */
Chris@0 212 public function routes() {
Chris@0 213 $collection = parent::routes();
Chris@0 214
Chris@0 215 // ResourceBase class does not support PUT method by some reason.
Chris@0 216 $definition = $this->getPluginDefinition();
Chris@0 217 $canonical_path = $definition['uri_paths']['canonical'];
Chris@0 218 $route = $this->getBaseRoute($canonical_path, 'PUT');
Chris@0 219 $route->addRequirements(['_content_type_format' => implode('|', $this->serializerFormats)]);
Chris@0 220 $collection->add('{{ plugin_id }}.PUT', $route);
Chris@0 221
Chris@0 222 return $collection;
Chris@0 223 }
Chris@0 224
Chris@0 225 /**
Chris@0 226 * Validates incoming record.
Chris@0 227 *
Chris@0 228 * @param mixed $record
Chris@0 229 * Data to validate.
Chris@0 230 *
Chris@0 231 * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
Chris@0 232 */
Chris@0 233 protected function validate($record) {
Chris@0 234 if (!is_array($record) || count($record) == 0) {
Chris@0 235 throw new BadRequestHttpException('No record content received.');
Chris@0 236 }
Chris@0 237
Chris@0 238 $allowed_fields = [
Chris@0 239 'title',
Chris@0 240 'description',
Chris@0 241 'price',
Chris@0 242 ];
Chris@0 243
Chris@0 244 if (count(array_diff(array_keys($record), $allowed_fields)) > 0) {
Chris@0 245 throw new BadRequestHttpException('Record structure is not correct.');
Chris@0 246 }
Chris@0 247
Chris@0 248 if (empty($record['title'])) {
Chris@0 249 throw new BadRequestHttpException('Title is required.');
Chris@0 250 }
Chris@0 251 elseif (isset($record['title']) && strlen($record['title']) > 255) {
Chris@0 252 throw new BadRequestHttpException('Title is too big.');
Chris@0 253 }
Chris@0 254 // @DCG Add more validation rules here.
Chris@0 255 }
Chris@0 256
Chris@0 257 /**
Chris@0 258 * Loads record from database.
Chris@0 259 *
Chris@0 260 * @param int $id
Chris@0 261 * The ID of the record.
Chris@0 262 *
Chris@0 263 * @return array
Chris@0 264 * The database record.
Chris@0 265 *
Chris@0 266 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
Chris@0 267 */
Chris@0 268 protected function loadRecord($id) {
Chris@0 269 $record = $this->dbConnection->query('SELECT * FROM {{ '{' }}{{ plugin_id }}{{ '}' }} WHERE id = :id', [':id' => $id])->fetchAssoc();
Chris@0 270 if (!$record) {
Chris@0 271 throw new NotFoundHttpException('The record was not found.');
Chris@0 272 }
Chris@0 273 return $record;
Chris@0 274 }
Chris@0 275
Chris@0 276 /**
Chris@0 277 * Updates record.
Chris@0 278 *
Chris@0 279 * @param int $id
Chris@0 280 * The ID of the record.
Chris@0 281 * @param array $record
Chris@0 282 * The record to validate.
Chris@0 283 *
Chris@0 284 * @return \Drupal\rest\ModifiedResourceResponse
Chris@0 285 * The HTTP response object.
Chris@0 286 */
Chris@0 287 protected function updateRecord($id, array $record) {
Chris@0 288
Chris@0 289 // Make sure the record already exists.
Chris@0 290 $this->loadRecord($id);
Chris@0 291
Chris@0 292 $this->validate($record);
Chris@0 293
Chris@0 294 $this->dbConnection->update('{{ plugin_id }}')
Chris@0 295 ->fields($record)
Chris@0 296 ->condition('id', $id)
Chris@0 297 ->execute();
Chris@0 298
Chris@0 299 $this->logger->notice('{{ plugin_label }} record @id has been updated.', ['@id' => $id]);
Chris@0 300
Chris@0 301 // Return the updated record in the response body.
Chris@0 302 $updated_record = $this->loadRecord($id);
Chris@0 303 return new ModifiedResourceResponse($updated_record, 200);
Chris@0 304 }
Chris@0 305
Chris@0 306 }