Chris@0: dbConnection = $db_connection; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { Chris@0: return new static( Chris@0: $configuration, Chris@0: $plugin_id, Chris@0: $plugin_definition, Chris@0: $container->getParameter('serializer.formats'), Chris@0: $container->get('logger.factory')->get('rest'), Chris@0: $container->get('database') Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Responds to GET requests. Chris@0: * Chris@0: * @param int $id Chris@0: * The ID of the record. Chris@0: * Chris@0: * @return \Drupal\rest\ResourceResponse Chris@0: * The response containing the record. Chris@0: * Chris@0: * @throws \Symfony\Component\HttpKernel\Exception\HttpException Chris@0: */ Chris@0: public function get($id) { Chris@0: return new ResourceResponse($this->loadRecord($id)); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Responds to POST requests and saves the new record. Chris@0: * Chris@0: * @param mixed $record Chris@0: * Data to write into the database. Chris@0: * Chris@0: * @return \Drupal\rest\ModifiedResourceResponse Chris@0: * The HTTP response object. Chris@0: */ Chris@0: public function post($record) { Chris@0: Chris@0: $this->validate($record); Chris@0: Chris@0: $id = $this->dbConnection->insert('{{ plugin_id }}') Chris@0: ->fields($record) Chris@0: ->execute(); Chris@0: Chris@0: $this->logger->notice('New {{ plugin_label|lower }} record has been created.'); Chris@0: Chris@0: $created_record = $this->loadRecord($id); Chris@0: Chris@0: // Return the newly created record in the response body. Chris@0: return new ModifiedResourceResponse($created_record, 201); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Responds to entity PATCH requests. Chris@0: * Chris@0: * @param int $id Chris@0: * The ID of the record. Chris@0: * @param mixed $record Chris@0: * Data to write into the database. Chris@0: * Chris@0: * @return \Drupal\rest\ModifiedResourceResponse Chris@0: * The HTTP response object. Chris@0: */ Chris@0: public function patch($id, $record) { Chris@0: $this->validate($record); Chris@0: return $this->updateRecord($id, $record); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Responds to entity PUT requests. Chris@0: * Chris@0: * @param int $id Chris@0: * The ID of the record. Chris@0: * @param mixed $record Chris@0: * Data to write into the database. Chris@0: * Chris@0: * @return \Drupal\rest\ModifiedResourceResponse Chris@0: * The HTTP response object. Chris@0: */ Chris@0: public function put($id, $record) { Chris@0: Chris@0: $this->validate($record); Chris@0: Chris@0: // Provide default values to make sure the record is completely replaced. Chris@0: $record += [ Chris@0: 'title' => '', Chris@0: 'description' => '', Chris@0: 'price' => 0, Chris@0: ]; Chris@0: Chris@0: return $this->updateRecord($id, $record); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Responds to entity DELETE requests. Chris@0: * Chris@0: * @param int $id Chris@0: * The ID of the record. Chris@0: * Chris@0: * @return \Drupal\rest\ModifiedResourceResponse Chris@0: * The HTTP response object. Chris@0: * Chris@0: * @throws \Symfony\Component\HttpKernel\Exception\HttpException Chris@0: */ Chris@0: public function delete($id) { Chris@0: Chris@0: // Make sure the record still exists. Chris@0: $this->loadRecord($id); Chris@0: Chris@0: $this->dbConnection->delete('{{ plugin_id }}') Chris@0: ->condition('id', $id) Chris@0: ->execute(); Chris@0: Chris@0: $this->logger->notice('{{ plugin_label }} record @id has been deleted.', ['@id' => $id]); Chris@0: Chris@0: // Deleted responses have an empty body. Chris@0: return new ModifiedResourceResponse(NULL, 204); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function getBaseRoute($canonical_path, $method) { Chris@0: $route = parent::getBaseRoute($canonical_path, $method); Chris@0: Chris@0: // Change ID validation pattern. Chris@0: if ($method != 'POST') { Chris@0: $route->setRequirement('id', '\d+'); Chris@0: } Chris@0: Chris@0: return $route; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function calculateDependencies() { Chris@0: return []; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function routes() { Chris@0: $collection = parent::routes(); Chris@0: Chris@0: // ResourceBase class does not support PUT method by some reason. Chris@0: $definition = $this->getPluginDefinition(); Chris@0: $canonical_path = $definition['uri_paths']['canonical']; Chris@0: $route = $this->getBaseRoute($canonical_path, 'PUT'); Chris@0: $route->addRequirements(['_content_type_format' => implode('|', $this->serializerFormats)]); Chris@0: $collection->add('{{ plugin_id }}.PUT', $route); Chris@0: Chris@0: return $collection; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Validates incoming record. Chris@0: * Chris@0: * @param mixed $record Chris@0: * Data to validate. Chris@0: * Chris@0: * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException Chris@0: */ Chris@0: protected function validate($record) { Chris@0: if (!is_array($record) || count($record) == 0) { Chris@0: throw new BadRequestHttpException('No record content received.'); Chris@0: } Chris@0: Chris@0: $allowed_fields = [ Chris@0: 'title', Chris@0: 'description', Chris@0: 'price', Chris@0: ]; Chris@0: Chris@0: if (count(array_diff(array_keys($record), $allowed_fields)) > 0) { Chris@0: throw new BadRequestHttpException('Record structure is not correct.'); Chris@0: } Chris@0: Chris@0: if (empty($record['title'])) { Chris@0: throw new BadRequestHttpException('Title is required.'); Chris@0: } Chris@0: elseif (isset($record['title']) && strlen($record['title']) > 255) { Chris@0: throw new BadRequestHttpException('Title is too big.'); Chris@0: } Chris@0: // @DCG Add more validation rules here. Chris@0: } Chris@0: Chris@0: /** Chris@0: * Loads record from database. Chris@0: * Chris@0: * @param int $id Chris@0: * The ID of the record. Chris@0: * Chris@0: * @return array Chris@0: * The database record. Chris@0: * Chris@0: * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException Chris@0: */ Chris@0: protected function loadRecord($id) { Chris@0: $record = $this->dbConnection->query('SELECT * FROM {{ '{' }}{{ plugin_id }}{{ '}' }} WHERE id = :id', [':id' => $id])->fetchAssoc(); Chris@0: if (!$record) { Chris@0: throw new NotFoundHttpException('The record was not found.'); Chris@0: } Chris@0: return $record; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Updates record. Chris@0: * Chris@0: * @param int $id Chris@0: * The ID of the record. Chris@0: * @param array $record Chris@0: * The record to validate. Chris@0: * Chris@0: * @return \Drupal\rest\ModifiedResourceResponse Chris@0: * The HTTP response object. Chris@0: */ Chris@0: protected function updateRecord($id, array $record) { Chris@0: Chris@0: // Make sure the record already exists. Chris@0: $this->loadRecord($id); Chris@0: Chris@0: $this->validate($record); Chris@0: Chris@0: $this->dbConnection->update('{{ plugin_id }}') Chris@0: ->fields($record) Chris@0: ->condition('id', $id) Chris@0: ->execute(); Chris@0: Chris@0: $this->logger->notice('{{ plugin_label }} record @id has been updated.', ['@id' => $id]); Chris@0: Chris@0: // Return the updated record in the response body. Chris@0: $updated_record = $this->loadRecord($id); Chris@0: return new ModifiedResourceResponse($updated_record, 200); Chris@0: } Chris@0: Chris@0: }