Skip to content

Commit

Permalink
Add validator of HTTP methods. Move list of http methods to separate …
Browse files Browse the repository at this point in the history
…method and add settings for it. Change twig template to generate the methods based on HTTP methods accrodingly (#3666)
  • Loading branch information
LOBsTerr authored and jmolivas committed Jan 10, 2018
1 parent 40c3bc7 commit 5aef231
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 8 deletions.
53 changes: 50 additions & 3 deletions src/Command/Generate/PluginRestResourceCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,20 @@ protected function execute(InputInterface $input, OutputInterface $output)
return 1;
}

$http_methods = $this->getHttpMethods();
$module = $input->getOption('module');
$class_name = $this->validator->validateClassName($input->getOption('class'));
$plugin_id = $input->getOption('plugin-id');
$plugin_label = $input->getOption('plugin-label');
$plugin_url = $input->getOption('plugin-url');
$plugin_states = $input->getOption('plugin-states');
$plugin_states = $this->validator->validateHttpMethods($input->getOption('plugin-states'), $http_methods);

$prepared_plugin = [];
foreach ($plugin_states as $plugin_state) {
$prepared_plugin[$plugin_state] = $http_methods[$plugin_state];
}

$this->generator->generate($module, $class_name, $plugin_label, $plugin_id, $plugin_url, $plugin_states);
$this->generator->generate($module, $class_name, $plugin_label, $plugin_id, $plugin_url, $prepared_plugin);

$this->chainQueue->addCommand('cache:rebuild', ['cache' => 'discovery']);

Expand Down Expand Up @@ -204,10 +210,11 @@ function ($class) {
$input->setOption('plugin-url', $plugin_url);
}


// --plugin-states option
$plugin_states = $input->getOption('plugin-states');
if (!$plugin_states) {
$states = ['GET', 'PUT', 'POST', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
$states = array_keys($this->getHttpMethods());
$plugin_states = $io->choice(
$this->trans('commands.generate.plugin.rest.resource.questions.plugin-states'),
$states,
Expand All @@ -217,5 +224,45 @@ function ($class) {

$input->setOption('plugin-states', $plugin_states);
}

}

/**
* Returns available HTTP methods.
*
* @return array
* Available HTTP methods.
*/
protected function getHttpMethods() {
return [
'GET' => [
'http_code' => 200,
'response_class' => 'ResourceResponse',
],
'PUT' => [
'http_code' => 201,
'response_class' => 'ModifiedResourceResponse',
],
'POST' => [
'http_code' => 200,
'response_class' => 'ModifiedResourceResponse',
],
'PATCH' => [
'http_code' => 204,
'response_class' => 'ModifiedResourceResponse',
],
'DELETE' => [
'http_code' => 204,
'response_class' => 'ModifiedResourceResponse',
],
'HEAD' => [
'http_code' => 200,
'response_class' => 'ResourceResponse',
],
'OPTIONS' => [
'http_code' => 200,
'response_class' => 'ResourceResponse',
],
];
}
}
22 changes: 22 additions & 0 deletions src/Utils/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,26 @@ public function validateExtensions($extensions_list, $type, DrupalStyle $io)

return $extensions;
}

/**
* Validate if http methods exist.
*
* @param array $httpMethods Array http methods.
* @param array $availableHttpMethods Array of available http methods.
*
* @return string
*/
public function validateHttpMethods($httpMethods, $availableHttpMethods)
{
if (empty($httpMethods)) {
return null;
}

$missing_methods = array_diff(array_values($httpMethods), array_keys($availableHttpMethods));
if (!empty($missing_methods)) {
throw new \InvalidArgumentException(sprintf('HTTP methods "%s" are invalid.', implode(', ', $missing_methods)));
}

return $httpMethods;
}
}
16 changes: 11 additions & 5 deletions templates/module/src/Plugin/Rest/Resource/rest.php.twig
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ namespace Drupal\{{module_name}}\Plugin\rest\resource;

{% block use_class %}
use Drupal\Core\Session\AccountProxyInterface;
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\AccessDeniedHttpException;
use Psr\Log\LoggerInterface;
{% endblock %}

{% block class_declaration %}
Expand Down Expand Up @@ -87,26 +88,31 @@ class {{ class_name }} extends ResourceBase {% endblock %}
);
}
{% endblock %}

{% block class_methods %}
{% for state in plugin_states %}
{% for state, state_settings in plugin_states %}

/**
* Responds to {{ state }} requests.
*
* Returns a list of bundles for specified entity.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
*
* @return \Drupal\rest\{{ state_settings.response_class }}
* The HTTP response object.
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
* Throws exception expected.
*/
public function {{ state|lower }}() {
public function {{ state|lower }}(EntityInterface $entity) {

// You must to implement the logic of your REST Resource here.
// Use current user after pass authentication to validate access.
if (!$this->currentUser->hasPermission('access content')) {
throw new AccessDeniedHttpException();
}

return new ResourceResponse("Implement REST State {{ state }}!");
return new {{ state_settings.response_class }}({{ (state == 'DELETE') ? 'NULL' : '$entity' }}, {{ state_settings.http_code }});
}
{% endfor %}
{% endblock %}

0 comments on commit 5aef231

Please sign in to comment.