Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663
This commit is contained in:
parent
eb34d130a8
commit
f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions
|
@ -15,13 +15,13 @@ function rest_help($route_name, RouteMatchInterface $route_match) {
|
|||
case 'help.page.rest':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The RESTful Web Services module provides a framework for exposing REST resources on your site. It provides support for content entities (see the <a href="!field">Field module help page</a> for more information about entities) such as content, users, taxonomy terms, etc.; REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. Other modules may add support for other types of REST resources. For more information, see the <a href="!rest">online documentation for the RESTful Web Services module</a>.', array('!rest' => 'https://www.drupal.org/documentation/modules/rest', '!field' => (\Drupal::moduleHandler()->moduleExists('field')) ? \Drupal::url('help.page', array('name' => 'field')) : '#')) . '</p>';
|
||||
$output .= '<p>' . t('The RESTful Web Services module provides a framework for exposing REST resources on your site. It provides support for content entities (see the <a href=":field">Field module help page</a> for more information about entities) such as content, users, taxonomy terms, etc.; REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. Other modules may add support for other types of REST resources. For more information, see the <a href=":rest">online documentation for the RESTful Web Services module</a>.', array(':rest' => 'https://www.drupal.org/documentation/modules/rest', ':field' => (\Drupal::moduleHandler()->moduleExists('field')) ? \Drupal::url('help.page', array('name' => 'field')) : '#')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Installing supporting modules') . '</dt>';
|
||||
$output .= '<dd>' . t('In order to use REST on a web site, you need to install modules that provide serialization and authentication services. You can use the Core module <a href="!hal">HAL</a> for serialization and <a href="!basic_auth">HTTP Basic Authentication</a> for authentication, or install a contributed or custom module.', array('!hal' => (\Drupal::moduleHandler()->moduleExists('hal')) ? \Drupal::url('help.page', array('name' => 'hal')) : '#', '!basic_auth' => (\Drupal::moduleHandler()->moduleExists('basic_auth')) ? \Drupal::url('help.page', array('name' => 'basic_auth')) : '#')) . '</dd>';
|
||||
$output .= '<dd>' . t('In order to use REST on a web site, you need to install modules that provide serialization and authentication services. You can use the Core module <a href=":hal">HAL</a> for serialization and <a href=":basic_auth">HTTP Basic Authentication</a> for authentication, or install a contributed or custom module.', array(':hal' => (\Drupal::moduleHandler()->moduleExists('hal')) ? \Drupal::url('help.page', array('name' => 'hal')) : '#', ':basic_auth' => (\Drupal::moduleHandler()->moduleExists('basic_auth')) ? \Drupal::url('help.page', array('name' => 'basic_auth')) : '#')) . '</dd>';
|
||||
$output .= '<dt>' . t('Enabling REST support for an entity type') . '</dt>';
|
||||
$output .= '<dd>' . t('REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. To enable support, you can use a <a href="!config">process based on configuration editing</a> or the contributed <a href="!restui">Rest UI module</a>.', array('!config' => 'https://www.drupal.org/documentation/modules/rest', '!restui' => 'https://www.drupal.org/project/restui')) . '</dd>';
|
||||
$output .= '<dd>' . t('REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. To enable support, you can use a <a href=":config">process based on configuration editing</a> or the contributed <a href=":restui">Rest UI module</a>.', array(':config' => 'https://www.drupal.org/documentation/modules/rest', ':restui' => 'https://www.drupal.org/project/restui')) . '</dd>';
|
||||
$output .= '<dd>' . t('You will also need to grant anonymous users permission to perform each of the REST operations you want to be available, and set up authentication properly to authorize web requests.') . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
|
|
@ -62,6 +62,18 @@ class RelationLinkManager extends LinkManagerBase implements RelationLinkManager
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationUri($entity_type, $bundle, $field_name, $context = array()) {
|
||||
// Per the interface documention of this method, the returned URI may
|
||||
// optionally also serve as the URL of a documentation page about this
|
||||
// field. However, the REST module does not currently implement such
|
||||
// a documentation page. Therefore, we return a URI assembled relative to
|
||||
// the site's base URL, which is sufficient to uniquely identify the site's
|
||||
// entity type + bundle + field for use in hypermedia formats, but we do
|
||||
// not take into account unclean URLs, language prefixing, or anything else
|
||||
// that would be required for Drupal to be able to respond with content
|
||||
// at this URL. If a module is installed that adds such content, but
|
||||
// requires this URL to be different (e.g., include a language prefix),
|
||||
// then the module must also override the RelationLinkManager class/service
|
||||
// to return the desired URL.
|
||||
$uri = $this->getLinkDomain() . "/rest/relation/$entity_type/$bundle/$field_name";
|
||||
$this->moduleHandler->alter('rest_relation_uri', $uri, $context);
|
||||
return $uri;
|
||||
|
|
|
@ -12,6 +12,10 @@ interface RelationLinkManagerInterface extends ConfigurableLinkManagerInterface
|
|||
/**
|
||||
* Gets the URI that corresponds to a field.
|
||||
*
|
||||
* When using hypermedia formats, this URI can be used to indicate which
|
||||
* field the data represents. Documentation about this field can also be
|
||||
* provided at this URI.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The bundle's entity type.
|
||||
* @param string $bundle
|
||||
|
|
|
@ -49,19 +49,21 @@ class TypeLinkManager extends LinkManagerBase implements TypeLinkManagerInterfac
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a type link for a bundle.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The bundle's entity type.
|
||||
* @param string $bundle
|
||||
* The name of the bundle.
|
||||
* @param array $context
|
||||
* Context of normalizer/serializer.
|
||||
*
|
||||
* @return string
|
||||
* The URI that identifies this bundle.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTypeUri($entity_type, $bundle, $context = array()) {
|
||||
// Per the interface documention of this method, the returned URI may
|
||||
// optionally also serve as the URL of a documentation page about this
|
||||
// bundle. However, the REST module does not currently implement such
|
||||
// a documentation page. Therefore, we return a URI assembled relative to
|
||||
// the site's base URL, which is sufficient to uniquely identify the site's
|
||||
// entity type and bundle for use in hypermedia formats, but we do not
|
||||
// take into account unclean URLs, language prefixing, or anything else
|
||||
// that would be required for Drupal to be able to respond with content
|
||||
// at this URL. If a module is installed that adds such content, but
|
||||
// requires this URL to be different (e.g., include a language prefix),
|
||||
// then the module must also override the TypeLinkManager class/service to
|
||||
// return the desired URL.
|
||||
$uri = $this->getLinkDomain() . "/rest/type/$entity_type/$bundle";
|
||||
$this->moduleHandler->alter('rest_type_uri', $uri, $context);
|
||||
return $uri;
|
||||
|
|
|
@ -14,7 +14,7 @@ use Drupal\Core\Render\RendererInterface;
|
|||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\views\Plugin\views\display\ResponseDisplayPluginInterface;
|
||||
use Drupal\views\Render\ViewsRenderPipelineSafeString;
|
||||
use Drupal\views\Render\ViewsRenderPipelineMarkup;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Plugin\views\display\PathPluginBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -143,7 +143,7 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getType() {
|
||||
public function getType() {
|
||||
return 'data';
|
||||
}
|
||||
|
||||
|
@ -335,7 +335,7 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
|
|||
// executed by an HTML agent.
|
||||
// @todo Decide how to support non-HTML in the render API in
|
||||
// https://www.drupal.org/node/2501313.
|
||||
$build['#markup'] = ViewsRenderPipelineSafeString::create($build['#markup']);
|
||||
$build['#markup'] = ViewsRenderPipelineMarkup::create($build['#markup']);
|
||||
}
|
||||
|
||||
parent::applyDisplayCachablityMetadata($build);
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
|
||||
namespace Drupal\rest\Plugin\views\style;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\views\Plugin\CacheablePluginInterface;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\Plugin\views\style\StylePluginBase;
|
||||
|
@ -27,7 +28,7 @@ use Symfony\Component\Serializer\SerializerInterface;
|
|||
* display_types = {"data"}
|
||||
* )
|
||||
*/
|
||||
class Serializer extends StylePluginBase implements CacheablePluginInterface {
|
||||
class Serializer extends StylePluginBase implements CacheableDependencyInterface {
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\views\Plugin\views\style\StylePluginBase::$usesRowPlugin.
|
||||
|
@ -155,8 +156,8 @@ class Serializer extends StylePluginBase implements CacheablePluginInterface {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCacheable() {
|
||||
return TRUE;
|
||||
public function getCacheMaxAge() {
|
||||
return Cache::PERMANENT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,4 +167,11 @@ class Serializer extends StylePluginBase implements CacheablePluginInterface {
|
|||
return ['request_format'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTags() {
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Drupal\rest\Tests;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\rest\Tests\RESTTestBase;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests special cases for node entities.
|
||||
|
@ -42,6 +42,40 @@ class NodeTest extends RESTTestBase {
|
|||
$this->drupalLogin($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes and attempts to create a node via a REST "post" http request.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
protected function postNode($data) {
|
||||
// Enable node creation via POST.
|
||||
$this->enableNodeConfiguration('POST', 'create');
|
||||
$this->enableService('entity:node', 'POST', 'json');
|
||||
|
||||
// Create a JSON version of a simple node with the title.
|
||||
$serialized = $this->container->get('serializer')->serialize($data, 'json');
|
||||
|
||||
// Post to the REST service to create the node.
|
||||
$this->httpRequest('/entity/node', 'POST', $serialized, 'application/json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the title on a newly created node.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Drupal\node\Entity\Node
|
||||
*/
|
||||
protected function assertNodeTitleMatch($data) {
|
||||
/** @var \Drupal\node\Entity\Node $node */
|
||||
// Load the newly created node.
|
||||
$node = Node::load(1);
|
||||
|
||||
// Test that the title is the same as what we posted.
|
||||
$this->assertEqual($node->title->value, $data['title'][0]['value']);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs various tests on nodes and their REST API.
|
||||
*/
|
||||
|
@ -90,4 +124,79 @@ class NodeTest extends RESTTestBase {
|
|||
// Make sure that the UUID of the node has not changed.
|
||||
$this->assertEqual($node->get('uuid')->getValue(), $updated_node->get('uuid')->getValue(), 'UUID was not changed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a node using json serialization.
|
||||
*/
|
||||
public function testCreate() {
|
||||
// Data to be used for serialization.
|
||||
$data = [
|
||||
'type' => [['target_id' => 'resttest']],
|
||||
'title' => [['value' => $this->randomString() ]],
|
||||
];
|
||||
|
||||
$this->postNode($data);
|
||||
|
||||
// Make sure the response is "CREATED".
|
||||
$this->assertResponse(201);
|
||||
|
||||
// Make sure the node was created and the title matches.
|
||||
$node = $this->assertNodeTitleMatch($data);
|
||||
|
||||
// Make sure the request returned a redirect header to view the node.
|
||||
$this->assertHeader('Location', $node->url('canonical', ['absolute' => TRUE]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bundle normalization when posting bundle as a simple string.
|
||||
*/
|
||||
public function testBundleNormalization() {
|
||||
// Data to be used for serialization.
|
||||
$data = [
|
||||
'type' => 'resttest',
|
||||
'title' => [['value' => $this->randomString() ]],
|
||||
];
|
||||
|
||||
$this->postNode($data);
|
||||
|
||||
// Make sure the response is "CREATED".
|
||||
$this->assertResponse(201);
|
||||
|
||||
// Make sure the node was created and the title matches.
|
||||
$this->assertNodeTitleMatch($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bundle normalization when posting using a simple string.
|
||||
*/
|
||||
public function testInvalidBundle() {
|
||||
// Data to be used for serialization.
|
||||
$data = [
|
||||
'type' => 'bad_bundle_name',
|
||||
'title' => [['value' => $this->randomString() ]],
|
||||
];
|
||||
|
||||
$this->postNode($data);
|
||||
|
||||
// Make sure the response is "Bad Request".
|
||||
$this->assertResponse(400);
|
||||
$this->assertResponseBody('{"error":"\"bad_bundle_name\" is not a valid bundle type for denormalization."}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test when the bundle is missing.
|
||||
*/
|
||||
public function testMissingBundle() {
|
||||
// Data to be used for serialization.
|
||||
$data = [
|
||||
'title' => [['value' => $this->randomString() ]],
|
||||
];
|
||||
|
||||
// testing
|
||||
$this->postNode($data);
|
||||
|
||||
// Make sure the response is "Bad Request".
|
||||
$this->assertResponse(400);
|
||||
$this->assertResponseBody('{"error":"A string must be provided as a bundle value."}');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,9 @@
|
|||
|
||||
namespace Drupal\rest\Tests;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\node\NodeInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Test helper class that provides a REST client method to send HTTP requests.
|
||||
|
@ -46,6 +44,14 @@ abstract class RESTTestBase extends WebTestBase {
|
|||
*/
|
||||
protected $defaultAuth;
|
||||
|
||||
|
||||
/**
|
||||
* The raw response body from http request operations.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $responseBody;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
|
@ -153,7 +159,7 @@ abstract class RESTTestBase extends WebTestBase {
|
|||
break;
|
||||
}
|
||||
|
||||
$response = $this->curlExec($curl_options);
|
||||
$this->responseBody = $this->curlExec($curl_options);
|
||||
|
||||
// Ensure that any changes to variables in the other thread are picked up.
|
||||
$this->refreshVariables();
|
||||
|
@ -163,9 +169,9 @@ abstract class RESTTestBase extends WebTestBase {
|
|||
$this->verbose($method . ' request to: ' . $url .
|
||||
'<hr />Code: ' . curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE) .
|
||||
'<hr />Response headers: ' . nl2br(print_r($headers, TRUE)) .
|
||||
'<hr />Response body: ' . $response);
|
||||
'<hr />Response body: ' . $this->responseBody);
|
||||
|
||||
return $response;
|
||||
return $this->responseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -383,9 +389,33 @@ abstract class RESTTestBase extends WebTestBase {
|
|||
$node->set('promote', NULL);
|
||||
$node->set('sticky', NULL);
|
||||
$node->set('revision_timestamp', NULL);
|
||||
$node->set('revision_log', NULL);
|
||||
$node->set('uid', NULL);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the HTTP request response body is identical to the expected
|
||||
* value.
|
||||
*
|
||||
* @param $expected
|
||||
* The first value to check.
|
||||
* @param $message
|
||||
* (optional) A message to display with the assertion. Do not translate
|
||||
* messages: use \Drupal\Component\Utility\SafeMarkup::format() to embed
|
||||
* variables in the message text, not t(). If left blank, a default message
|
||||
* will be displayed.
|
||||
* @param $group
|
||||
* (optional) The group this message is in, which is displayed in a column
|
||||
* in test output. Use 'Debug' to indicate this is debugging output. Do not
|
||||
* translate this string. Defaults to 'Other'; most tests do not override
|
||||
* this default.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the assertion succeeded, FALSE otherwise.
|
||||
*/
|
||||
protected function assertResponseBody($expected, $message = '', $group = 'REST Response') {
|
||||
return $this->assertIdentical($expected, $this->responseBody, $message ? $message : strtr('Response body @expected (expected) is equal to @response (actual).', array('@expected' => var_export($expected, TRUE), '@response' => var_export($this->responseBody, TRUE))), $group);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -395,7 +395,7 @@ class StyleSerializerTest extends PluginTestBase {
|
|||
$expected[] = $expected_row;
|
||||
}
|
||||
|
||||
$this->assertIdentical($this->drupalGetJSON('test/serialize/field'), $expected);
|
||||
$this->assertIdentical($this->drupalGetJSON('test/serialize/field'), $this->castSafeStrings($expected));
|
||||
|
||||
// Test a random aliases for fields, they should be replaced.
|
||||
$alias_map = array(
|
||||
|
@ -430,7 +430,7 @@ class StyleSerializerTest extends PluginTestBase {
|
|||
$expected[] = $expected_row;
|
||||
}
|
||||
|
||||
$this->assertIdentical($this->drupalGetJSON('test/serialize/field'), $expected);
|
||||
$this->assertIdentical($this->drupalGetJSON('test/serialize/field'), $this->castSafeStrings($expected));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Reference in a new issue