Update to Drupal 8.2.4. For more information, see https://www.drupal.org/project/drupal/releases/8.2.4
This commit is contained in:
parent
0a95b8440e
commit
8544b60b39
|
@ -3,6 +3,9 @@ encouraged to submit issues and changes (patches) to improve Drupal, and to
|
|||
contribute in other ways -- see https://www.drupal.org/contribute to find out
|
||||
how.
|
||||
|
||||
This file lists the active maintainers. For a list of past maintainers, see:
|
||||
https://www.drupal.org/core/maintainers/past
|
||||
|
||||
|
||||
Core committers
|
||||
---------------
|
||||
|
@ -53,11 +56,10 @@ Actions
|
|||
- ?
|
||||
|
||||
Aggregator
|
||||
- Paris Liakos 'ParisLiakos' https://www.drupal.org/u/parisliakos
|
||||
- ?
|
||||
|
||||
Ajax
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Earl Miles 'merlinofchaos' https://www.drupal.org/u/merlinofchaos
|
||||
- Tim Plunkett 'tim.plunkett' https://www.drupal.org/u/tim.plunkett
|
||||
|
||||
Asset Library API
|
||||
|
@ -73,19 +75,17 @@ Ban
|
|||
- ?
|
||||
|
||||
Bartik
|
||||
- Jen Simmons 'jensimmons' https://www.drupal.org/u/jensimmons
|
||||
- Emma Maria Karayiannis 'emma.maria' https://www.drupal.org/u/emma.maria
|
||||
|
||||
Base system
|
||||
- Damien Tournoud 'damien-tournoud' https://www.drupal.org/u/damien-tournoud
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- ?
|
||||
|
||||
Basic Auth
|
||||
- Klaus Purer 'klausi' https://www.drupal.org/u/klausi
|
||||
- Juampy Novillo Requena 'juampy' https://www.drupal.org/u/juampy
|
||||
|
||||
Batch API
|
||||
- Yves Chedemois 'yched' https://www.drupal.org/u/yched
|
||||
- ?
|
||||
|
||||
BigPipe
|
||||
- Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers
|
||||
|
@ -109,9 +109,7 @@ Breakpoint
|
|||
- Marc Drummond 'mdrummond' https://www.drupal.org/u/mdrummond
|
||||
|
||||
Cache
|
||||
- Damien Tournoud 'damien-tournoud' https://www.drupal.org/u/damien-tournoud
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
- Mark Sonnabaum 'msonnabaum' https://www.drupal.org/u/msonnabaum
|
||||
|
||||
CKEditor
|
||||
- Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers
|
||||
|
@ -130,13 +128,11 @@ Comment
|
|||
- Andrey Postnikov 'andypost' https://www.drupal.org/u/andypost
|
||||
|
||||
Configuration API
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- Alex Pott 'alexpott' https://www.drupal.org/u/alexpott
|
||||
- Matthew Tift 'mtift' https://www.drupal.org/u/mtift
|
||||
|
||||
Configuration Entity API
|
||||
- Alex Pott 'alexpott' https://www.drupal.org/u/alexpott
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- Tim Plunkett 'tim.plunkett' https://www.drupal.org/u/tim.plunkett
|
||||
|
||||
Configuration UI
|
||||
|
@ -159,10 +155,10 @@ Content Translation
|
|||
- Francesco Placella 'plach' https://www.drupal.org/u/plach
|
||||
|
||||
Contextual
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- ?
|
||||
|
||||
Cron
|
||||
- Derek Wright 'dww' https://www.drupal.org/u/dww
|
||||
- ?
|
||||
|
||||
CSS
|
||||
- John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin
|
||||
|
@ -175,14 +171,13 @@ Database API
|
|||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
|
||||
PostgreSQL DB driver
|
||||
- Damien Tournoud 'damien-tournoud' https://www.drupal.org/u/damien-tournoud
|
||||
- Josh Waihi 'fiasco' https://www.drupal.org/u/fiasco
|
||||
- ?
|
||||
|
||||
Sqlite DB driver
|
||||
- Damien Tournoud 'damien-tournoud' https://www.drupal.org/u/damien-tournoud
|
||||
- ?
|
||||
|
||||
Database Logging
|
||||
- Khalid Baheyeldin 'kbahey' https://www.drupal.org/u/kbahey
|
||||
- ?
|
||||
|
||||
Database Update API
|
||||
- ?
|
||||
|
@ -203,7 +198,6 @@ Editor
|
|||
- Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers
|
||||
|
||||
Entity API
|
||||
- Wolfgang Ziegler 'fago' https://www.drupal.org/u/fago
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
- Sascha Grossenbacher 'Berdir' https://www.drupal.org/u/berdir
|
||||
- Francesco Placella 'plach' https://www.drupal.org/u/plach
|
||||
|
@ -213,7 +207,6 @@ Extension API
|
|||
- ?
|
||||
|
||||
Field API
|
||||
- Yves Chedemois 'yched' https://www.drupal.org/u/yched
|
||||
- Andrei Mateescu 'amateescu' https://www.drupal.org/u/amateescu
|
||||
|
||||
Field UI
|
||||
|
@ -221,19 +214,16 @@ Field UI
|
|||
- Andrei Mateescu 'amateescu' https://www.drupal.org/u/amateescu
|
||||
|
||||
File
|
||||
- Andrew Morton 'drewish' https://www.drupal.org/u/drewish
|
||||
- Aaron Winborn 'aaron' https://www.drupal.org/u/aaron
|
||||
- ?
|
||||
|
||||
Filter
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- ?
|
||||
|
||||
Forum
|
||||
- Lee Rowlands 'larowlan' https://www.drupal.org/u/larowlan
|
||||
|
||||
Form API
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Wolfgang Ziegler 'fago' https://www.drupal.org/u/fago
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- Tim Plunkett 'tim.plunkett' https://www.drupal.org/u/tim.plunkett
|
||||
|
||||
History
|
||||
|
@ -266,23 +256,25 @@ Link Field
|
|||
- Weber Macedo 'Mac_Weber' https://www.drupal.org/u/mac_weber
|
||||
|
||||
Lock
|
||||
- Damien Tournoud 'damien-tournoud' https://www.drupal.org/u/damien-tournoud
|
||||
- ?
|
||||
|
||||
Mail
|
||||
- ?
|
||||
|
||||
Markup
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- ?
|
||||
|
||||
Migrate
|
||||
- Adam Globus-Hoenich 'phenaproxima' https://www.drupal.org/u/phenaproxima
|
||||
- Ben Dougherty 'benjy' https://www.drupal.org/u/benjy
|
||||
- Lucas Hedding 'heddn' https://www.drupal.org/u/heddn
|
||||
- Michael Anello 'ultimike' https://www.drupal.org/u/ultimike
|
||||
- Mike Ryan 'mikeryan' https://www.drupal.org/u/mikeryan
|
||||
- Vicki Spagnolo 'quietone' https://www.drupal.org/u/quietone
|
||||
|
||||
Migrate (Drupal)
|
||||
- Ben Dougherty 'benjy' https://www.drupal.org/u/benjy
|
||||
- Lucas Hedding 'heddn' https://www.drupal.org/u/heddn
|
||||
- Michael Anello 'ultimike' https://www.drupal.org/u/ultimike
|
||||
- Mike Ryan 'mikeryan' https://www.drupal.org/u/mikeryan
|
||||
- Vicki Spagnolo 'quietone' https://www.drupal.org/u/quietone
|
||||
|
@ -299,16 +291,15 @@ Menu UI
|
|||
- ?
|
||||
|
||||
Node
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
- ?
|
||||
|
||||
Node Access
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- Ken Rickard 'agentrickard' https://www.drupal.org/u/agentrickard
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- Jess Myrbo 'xjm' https://www.drupal.org/u/xjm
|
||||
|
||||
Options
|
||||
- Yves Chedemois 'yched' https://www.drupal.org/u/yched
|
||||
- ?
|
||||
|
||||
Outside In
|
||||
- Ted Bowman 'tedbow' https://www.drupal.org/u/tedbow
|
||||
|
@ -327,7 +318,6 @@ Plugin
|
|||
|
||||
Queue
|
||||
- James Gilliland 'neclimdul' https://www.drupal.org/u/neclimdul
|
||||
- Mark Sonnabaum 'msonnabaum' https://www.drupal.org/u/msonnabaum
|
||||
|
||||
Quick Edit
|
||||
- Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers
|
||||
|
@ -337,8 +327,8 @@ RDF
|
|||
- Stéphane Corlosquet 'scor' https://www.drupal.org/u/scor
|
||||
|
||||
Render API
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
|
||||
Request Processing
|
||||
- Larry Garfield 'Crell' https://www.drupal.org/u/crell
|
||||
|
@ -388,10 +378,9 @@ System (module)
|
|||
Taxonomy
|
||||
- Jess Myrbo 'xjm' https://www.drupal.org/u/xjm
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
- Benjamin Doherty 'bangpound' https://www.drupal.org/u/bangpound
|
||||
|
||||
Telephone
|
||||
- Dave Reid 'dave-reid' https://www.drupal.org/u/dave-reid
|
||||
- ?
|
||||
|
||||
Testing framework
|
||||
- Alex Pott 'alexpott' https://www.drupal.org/u/alexpott
|
||||
|
@ -409,7 +398,7 @@ Theme API
|
|||
- Lauri Eskola 'lauriii' https://www.drupal.org/u/lauriii
|
||||
|
||||
Token
|
||||
- Dave Reid 'davereid' https://www.drupal.org/u/davereid
|
||||
- ?
|
||||
|
||||
Toolbar
|
||||
- Théodore Biadala 'nod_' https://www.drupal.org/u/nod_
|
||||
|
@ -418,22 +407,19 @@ Tour
|
|||
- Nick Schuch 'nick_schuch' https://www.drupal.org/u/nick_schuch
|
||||
|
||||
Tracker
|
||||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
- ?
|
||||
|
||||
Transliteration
|
||||
- Andrei Mateescu 'amateescu' https://www.drupal.org/u/amateescu
|
||||
- Damien Tournoud 'damien-tournoud' https://www.drupal.org/u/damien-tournoud
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
|
||||
Typed Data
|
||||
- Wolfgang Ziegler 'fago' https://www.drupal.org/u/fago
|
||||
|
||||
Update UI
|
||||
- Derek Wright 'dww' https://www.drupal.org/u/dww
|
||||
- ?
|
||||
|
||||
User
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
|
||||
Views
|
||||
- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner
|
||||
|
@ -442,18 +428,11 @@ Views
|
|||
- Jess Myrbo 'xjm' https://www.drupal.org/u/xjm
|
||||
- Len Swaneveld 'Lendude' https://www.drupal.org/u/lendude
|
||||
|
||||
Views UI
|
||||
- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner
|
||||
- Tim Plunkett 'tim.plunkett' https://www.drupal.org/u/tim.plunkett
|
||||
- Damian Lee 'damiankloip' https://www.drupal.org/u/damiankloip
|
||||
- Len Swaneveld 'Lendude' https://www.drupal.org/u/lendude
|
||||
|
||||
Topic maintainers
|
||||
-----------------
|
||||
|
||||
Accessibility
|
||||
- Mike Gifford 'mgifford' https://www.drupal.org/u/mgifford
|
||||
- Jesse Renée Beach 'jessebeach' https://www.drupal.org/u/jessebeach
|
||||
- Andrew Macpherson 'andrewmacpherson' https://www.drupal.org/u/andrewmacpherson
|
||||
|
||||
Documentation
|
||||
|
@ -492,24 +471,16 @@ re-architect or otherwise improve large areas of Drupal core. See
|
|||
https://www.drupal.org/community-initiatives/drupal-core for more information on
|
||||
their responsibilities. The initiative coordinators for Drupal 8 are:
|
||||
|
||||
Configuration management
|
||||
- Greg Dunlap 'heyrocker' https://www.drupal.org/u/heyrocker
|
||||
|
||||
Design
|
||||
- Jeff Burns 'Jeff Burnz' https://www.drupal.org/u/jeff-burnz
|
||||
|
||||
Mobile
|
||||
- John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin
|
||||
|
||||
Multi-lingual
|
||||
- Gábor Hojtsy 'Gábor Hojtsy' https://www.drupal.org/u/gábor-hojtsy
|
||||
|
||||
Web services
|
||||
- Larry Garfield 'Crell' https://www.drupal.org/u/crell
|
||||
|
||||
Workflow Initiative
|
||||
- Dick Olsson 'dixon_' https://www.drupal.org/u/dixon_
|
||||
|
||||
PHPUnit Initiative
|
||||
- Klaus Purer 'klausi' https://www.drupal.org/u/klausi
|
||||
- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner
|
||||
|
||||
Provisional membership: None at this time.
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"symfony/psr-http-message-bridge": "v0.2",
|
||||
"zendframework/zend-diactoros": "~1.1",
|
||||
"composer/semver": "~1.0",
|
||||
"paragonie/random_compat": "~1.0",
|
||||
"paragonie/random_compat": "^1|^2",
|
||||
"asm89/stack-cors": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
|
@ -1073,8 +1073,9 @@
|
|||
* yourmodule/tests/src/Unit directory, according to the PSR-4 standard.
|
||||
* - Your test class needs a phpDoc comment block with a description and
|
||||
* a @group annotation, which gives information about the test.
|
||||
* - Methods in your test class whose names start with 'test' are the actual
|
||||
* test cases. Each one should test a logical subset of the functionality.
|
||||
* - Add test cases by adding method names that start with 'test' and have no
|
||||
* arguments, for example testYourTestCase(). Each one should test a logical
|
||||
* subset of the functionality.
|
||||
* For more details, see:
|
||||
* - https://www.drupal.org/phpunit for full documentation on how to write
|
||||
* PHPUnit tests for Drupal.
|
||||
|
@ -1110,9 +1111,9 @@
|
|||
* set up content types and similar procedures.
|
||||
* - In some cases, you may need to write a test module to support your test;
|
||||
* put such modules under the yourmodule/tests/modules directory.
|
||||
* - Methods in your test class whose names start with 'test', and which have
|
||||
* no arguments, are the actual test cases. Each one should test a logical
|
||||
* subset of the functionality, and each one runs in a new, isolated test
|
||||
* - Add test cases by adding method names that start with 'test' and have no
|
||||
* arguments, for example testYourTestCase(). Each one should test a logical
|
||||
* subset of the functionality. Each method runs in a new, isolated test
|
||||
* environment, so it can only rely on the setUp() method, not what has
|
||||
* been set up by other test methods.
|
||||
* For more details, see:
|
||||
|
@ -1121,6 +1122,52 @@
|
|||
* - @link oo_conventions Object-oriented programming topic @endlink for more
|
||||
* on PSR-4, namespaces, and where to place classes.
|
||||
*
|
||||
* @section write_functional_phpunit Write functional PHP tests (phpunit)
|
||||
* Functional tests extend the BrowserTestBase base class, and use PHPUnit as
|
||||
* their underlying framework. They use a simulated browser, in which the test
|
||||
* can click links, visit URLs, post to forms, etc. To write a functional test:
|
||||
* - Extend \Drupal\Tests\BrowserTestBase.
|
||||
* - Place the test in the yourmodule/tests/src/Functional/ directory and use
|
||||
* the \Drupal\Tests\yourmodule\Functional namespace.
|
||||
* - Add a @group annotation. For example, if the test is for a Drupal 6
|
||||
* migration process, the group core uses is migrate_drupal_6. Use yourmodule
|
||||
* as the group name if the test does not belong to another larger group.
|
||||
* - You may also override the default setUp() method, which can be used to set
|
||||
* up content types and similar procedures. Don't forget to call the parent
|
||||
* method.
|
||||
* - In some cases, you may need to write a test module to support your test;
|
||||
* put such modules under the yourmodule/tests/modules directory.
|
||||
* - Add test cases by adding method names that start with 'test' and have no
|
||||
* arguments, for example testYourTestCase(). Each one should test a logical
|
||||
* subset of the functionality. Each method runs in a new, isolated test
|
||||
* environment, so it can only rely on the setUp() method, not what has
|
||||
* been set up by other test methods.
|
||||
* For more details, see:
|
||||
* - https://www.drupal.org/docs/8/phpunit/phpunit-browser-test-tutorial for
|
||||
* a full tutorial on how to write functional PHPUnit tests for Drupal.
|
||||
* - https://www.drupal.org/phpunit for the full documentation on how to write
|
||||
* PHPUnit tests for Drupal.
|
||||
*
|
||||
* @section write_jsfunctional_phpunit Write functional JavaScript tests (phpunit)
|
||||
* To write a functional test that relies on JavaScript:
|
||||
* - Extend \Drupal\FunctionalJavaScriptTests\JavascriptTestBase.
|
||||
* - Place the test into the yourmodule/tests/src/FunctionalJavascript/
|
||||
* directory and use the \Drupal\Tests\yourmodule\FunctionalJavascript
|
||||
* namespace.
|
||||
* - Add a @group annotation. Use yourmodule as the group name if the test does
|
||||
* not belong to another larger group.
|
||||
* - Set up PhantomJS; see http://phantomjs.org/download.html.
|
||||
* - To run tests, see core/tests/README.md.
|
||||
* - When clicking a link/button with Ajax behavior attached, keep in mind that
|
||||
* the underlying browser might take time to deliver changes to the HTML. Use
|
||||
* $this->assertSession()->assertWaitOnAjaxRequest() to wait for the Ajax
|
||||
* request to finish.
|
||||
* For more details, see:
|
||||
* - https://www.drupal.org/docs/8/phpunit/phpunit-javascript-testing-tutorial
|
||||
* for a full tutorial on how to write PHPUnit JavaScript tests for Drupal.
|
||||
* - https://www.drupal.org/phpunit for the full documentation on how to write
|
||||
* PHPUnit tests for Drupal.
|
||||
*
|
||||
* @section running Running tests
|
||||
* You can run both Simpletest and PHPUnit tests by enabling the core Testing
|
||||
* module (core/modules/simpletest). Once that module is enabled, tests can be
|
||||
|
@ -2493,7 +2540,7 @@ function hook_validation_constraint_alter(array &$definitions) {
|
|||
* this class is subscribed to, and which methods on the class should be
|
||||
* called for each one. Example:
|
||||
* @code
|
||||
* public function getSubscribedEvents() {
|
||||
* public static function getSubscribedEvents() {
|
||||
* // Subscribe to kernel terminate with priority 100.
|
||||
* $events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
|
||||
* // Subscribe to kernel request with default priority of 0.
|
||||
|
|
|
@ -539,12 +539,12 @@ function entity_get_display($entity_type, $bundle, $view_mode) {
|
|||
* When the entity form display is not available in configuration, you can
|
||||
* create a new EntityFormDisplay object using:
|
||||
* @code
|
||||
* $values = ('entity_form_display', array(
|
||||
* $values = array(
|
||||
* 'targetEntityType' => $entity_type,
|
||||
* 'bundle' => $bundle,
|
||||
* 'mode' => $form_mode,
|
||||
* 'status' => TRUE,
|
||||
* ));
|
||||
* );
|
||||
* \Drupal::entityTypeManager()
|
||||
* ->getStorage('entity_form_display')
|
||||
* ->create($values);
|
||||
|
|
|
@ -81,7 +81,7 @@ class Drupal {
|
|||
/**
|
||||
* The current system version.
|
||||
*/
|
||||
const VERSION = '8.2.3';
|
||||
const VERSION = '8.2.4';
|
||||
|
||||
/**
|
||||
* Core API compatibility.
|
||||
|
|
|
@ -36,6 +36,16 @@ class DiffFormatter {
|
|||
*/
|
||||
public $trailing_context_lines = 0;
|
||||
|
||||
/**
|
||||
* The line stats.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $line_stats = array(
|
||||
'counter' => array('x' => 0, 'y' => 0),
|
||||
'offset' => array('x' => 0, 'y' => 0),
|
||||
);
|
||||
|
||||
/**
|
||||
* Format a diff.
|
||||
*
|
||||
|
|
|
@ -54,7 +54,7 @@ class CsrfAccessCheck implements RoutingAccessInterface {
|
|||
$path = str_replace("{{$param}}", $value, $path);
|
||||
}
|
||||
|
||||
if ($this->csrfToken->validate($request->query->get('token'), $path)) {
|
||||
if ($this->csrfToken->validate($request->query->get('token', ''), $path)) {
|
||||
$result = AccessResult::allowed();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -87,7 +87,7 @@ class CsrfTokenGenerator {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return $token === $this->computeToken($seed, $value);
|
||||
return Crypt::hashEquals($this->computeToken($seed, $value), $token);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,6 +34,11 @@ abstract class DraggableListBuilder extends ConfigEntityListBuilder implements F
|
|||
*/
|
||||
protected $weightKey = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $limit = FALSE;
|
||||
|
||||
/**
|
||||
* The form builder.
|
||||
*
|
||||
|
|
|
@ -19,16 +19,6 @@ class DiffFormatter extends DiffFormatterBase {
|
|||
*/
|
||||
protected $rows = array();
|
||||
|
||||
/**
|
||||
* The line stats.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $line_stats = array(
|
||||
'counter' => array('x' => 0, 'y' => 0),
|
||||
'offset' => array('x' => 0, 'y' => 0),
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates a DiffFormatter to render diffs in a table.
|
||||
*
|
||||
|
|
|
@ -348,13 +348,10 @@ class EntityAutocomplete extends Textfield {
|
|||
public static function extractEntityIdFromAutocompleteInput($input) {
|
||||
$match = NULL;
|
||||
|
||||
// Take "label (entity id)', match the ID from parenthesis when it's a
|
||||
// number.
|
||||
if (preg_match("/.+\s\((\d+)\)/", $input, $matches)) {
|
||||
$match = $matches[1];
|
||||
}
|
||||
// Match the ID when it's a string (e.g. for config entity types).
|
||||
elseif (preg_match("/.+\s\(([\w.]+)\)/", $input, $matches)) {
|
||||
// Take "label (entity id)', match the ID from inside the parentheses.
|
||||
// @todo Add support for entities containing parentheses in their ID.
|
||||
// @see https://www.drupal.org/node/2520416
|
||||
if (preg_match("/.+\s\(([^\)]+)\)/", $input, $matches)) {
|
||||
$match = $matches[1];
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ abstract class EntityDisplayBase extends ConfigEntityBase implements EntityDispl
|
|||
protected $plugins = array();
|
||||
|
||||
/**
|
||||
* Context in which this entity will be used (e.g. 'display', 'form').
|
||||
* Context in which this entity will be used (e.g. 'view', 'form').
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@ use Drupal\Core\Field\FieldItemInterface;
|
|||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Theme\Registry;
|
||||
use Drupal\Core\TypedData\TranslatableInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
|
@ -54,6 +55,13 @@ class EntityViewBuilder extends EntityHandlerBase implements EntityHandlerInterf
|
|||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The theme registry.
|
||||
*
|
||||
* @var \Drupal\Core\Theme\Registry
|
||||
*/
|
||||
protected $themeRegistry;
|
||||
|
||||
/**
|
||||
* The EntityViewDisplay objects created for individual field rendering.
|
||||
*
|
||||
|
@ -72,12 +80,15 @@ class EntityViewBuilder extends EntityHandlerBase implements EntityHandlerInterf
|
|||
* The entity manager service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Theme\Registry $theme_registry
|
||||
* The theme registry.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager) {
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, Registry $theme_registry = NULL) {
|
||||
$this->entityTypeId = $entity_type->id();
|
||||
$this->entityType = $entity_type;
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->languageManager = $language_manager;
|
||||
$this->themeRegistry = $theme_registry ?: \Drupal::service('theme.registry');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +98,8 @@ class EntityViewBuilder extends EntityHandlerBase implements EntityHandlerInterf
|
|||
return new static(
|
||||
$entity_type,
|
||||
$container->get('entity.manager'),
|
||||
$container->get('language_manager')
|
||||
$container->get('language_manager'),
|
||||
$container->get('theme.registry')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -148,7 +160,6 @@ class EntityViewBuilder extends EntityHandlerBase implements EntityHandlerInterf
|
|||
$this->moduleHandler()->alter('entity_view_mode', $view_mode, $entity, $context);
|
||||
|
||||
$build = array(
|
||||
'#theme' => $this->entityTypeId,
|
||||
"#{$this->entityTypeId}" => $entity,
|
||||
'#view_mode' => $view_mode,
|
||||
// Collect cache defaults for this entity.
|
||||
|
@ -159,6 +170,11 @@ class EntityViewBuilder extends EntityHandlerBase implements EntityHandlerInterf
|
|||
),
|
||||
);
|
||||
|
||||
// Add the default #theme key if a template exists for it.
|
||||
if ($this->themeRegistry->getRuntime()->has($this->entityTypeId)) {
|
||||
$build['#theme'] = $this->entityTypeId;
|
||||
}
|
||||
|
||||
// Cache the rendered output if permitted by the view mode and global entity
|
||||
// type configuration.
|
||||
if ($this->isViewModeCacheable($view_mode) && !$entity->isNew() && $entity->isDefaultRevision() && $this->entityType->isRenderCacheable()) {
|
||||
|
|
|
@ -35,13 +35,18 @@ interface QueryInterface extends AlterableInterface {
|
|||
*
|
||||
* @param $field
|
||||
* Name of the field being queried. It must contain a field name, optionally
|
||||
* followed by a column name. The column can be "entity" for reference
|
||||
* fields and that can be followed similarly by a field name and so on. Some
|
||||
* examples:
|
||||
* followed by a column name. The column can be the reference property,
|
||||
* usually "entity", for reference fields and that can be followed
|
||||
* similarly by a field name and so on. Additionally, the target entity type
|
||||
* can be specified by appending the ":target_entity_type_id" to "entity".
|
||||
* Some examples:
|
||||
* - nid
|
||||
* - tags.value
|
||||
* - tags
|
||||
* - tags.entity.name
|
||||
* - tags.entity:taxonomy_term.name
|
||||
* - uid.entity.name
|
||||
* - uid.entity:user.name
|
||||
* "tags" "is the same as "tags.value" as value is the default column.
|
||||
* If two or more conditions have the same field names they apply to the
|
||||
* same delta within that field. In order to limit the condition to a
|
||||
|
|
|
@ -6,6 +6,8 @@ use Drupal\Core\Database\Query\SelectInterface;
|
|||
use Drupal\Core\Entity\Query\QueryException;
|
||||
use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
|
||||
use Drupal\Core\Entity\Sql\TableMappingInterface;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
|
||||
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Adds tables and fields to the SQL entity query.
|
||||
|
@ -253,10 +255,20 @@ class Tables implements TablesInterface {
|
|||
$relationship_specifier = $specifiers[$key + 1];
|
||||
$next_index_prefix = $relationship_specifier;
|
||||
}
|
||||
$entity_type_id = NULL;
|
||||
// Relationship specifier can also contain the entity type ID, i.e.
|
||||
// entity:node, entity:user or entity:taxonomy.
|
||||
if (strpos($relationship_specifier, ':') !== FALSE) {
|
||||
list($relationship_specifier, $entity_type_id) = explode(':', $relationship_specifier, 2);
|
||||
}
|
||||
// Check for a valid relationship.
|
||||
if (isset($propertyDefinitions[$relationship_specifier]) && $field_storage->getPropertyDefinition('entity')->getDataType() == 'entity_reference' ) {
|
||||
// If it is, use the entity type.
|
||||
$entity_type_id = $propertyDefinitions[$relationship_specifier]->getTargetDefinition()->getEntityTypeId();
|
||||
if (isset($propertyDefinitions[$relationship_specifier]) && $propertyDefinitions[$relationship_specifier] instanceof DataReferenceDefinitionInterface) {
|
||||
// If it is, use the entity type if specified already, otherwise use
|
||||
// the definition.
|
||||
$target_definition = $propertyDefinitions[$relationship_specifier]->getTargetDefinition();
|
||||
if (!$entity_type_id && $target_definition instanceof EntityDataDefinitionInterface) {
|
||||
$entity_type_id = $target_definition->getEntityTypeId();
|
||||
}
|
||||
$entity_type = $this->entityManager->getDefinition($entity_type_id);
|
||||
$field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
||||
// Add the new entity base table using the table and sql column.
|
||||
|
|
|
@ -1257,7 +1257,11 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
foreach ($storage_definition->getColumns() as $column => $attributes) {
|
||||
$column_name = $table_mapping->getFieldColumnName($storage_definition, $column);
|
||||
// Serialize the value if specified in the column schema.
|
||||
$record[$column_name] = !empty($attributes['serialize']) ? serialize($item->$column) : $item->$column;
|
||||
$value = $item->$column;
|
||||
if (!empty($attributes['serialize'])) {
|
||||
$value = serialize($value);
|
||||
}
|
||||
$record[$column_name] = drupal_schema_get_field_value($attributes, $value);
|
||||
}
|
||||
$query->values($record);
|
||||
if ($this->entityType->isRevisionable()) {
|
||||
|
|
|
@ -168,6 +168,10 @@ class EntityReferenceEntityFormatter extends EntityReferenceFormatterBase implem
|
|||
$recursive_render_id = $items->getFieldDefinition()->getTargetEntityTypeId()
|
||||
. $items->getFieldDefinition()->getTargetBundle()
|
||||
. $items->getName()
|
||||
// We include the referencing entity, so we can render default images
|
||||
// without hitting recursive protections.
|
||||
. $items->getEntity()->id()
|
||||
. $entity->getEntityTypeId()
|
||||
. $entity->id();
|
||||
|
||||
if (isset(static::$recursiveRenderDepth[$recursive_render_id])) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Core\Field\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Defines the 'uuid' entity field type.
|
||||
|
@ -48,4 +49,12 @@ class UuidItem extends StringItem {
|
|||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
|
||||
$values['value'] = \Drupal::service('uuid')->generate();
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
|
|||
/**
|
||||
* Constructs a WidgetBase object.
|
||||
*
|
||||
* @param array $plugin_id
|
||||
* @param string $plugin_id
|
||||
* The plugin_id for the widget.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
|
|
|
@ -318,7 +318,7 @@ class LanguageManager implements LanguageManagerInterface {
|
|||
'th' => array('Thai', 'ภาษาไทย'),
|
||||
'tr' => array('Turkish', 'Türkçe'),
|
||||
'tyv' => array('Tuvan', 'Тыва дыл'),
|
||||
'ug' => array('Uyghur', 'Уйғур'),
|
||||
'ug' => array('Uyghur', /* Left-to-right marker "" */ 'ئۇيغۇرچە', LanguageInterface::DIRECTION_RTL),
|
||||
'uk' => array('Ukrainian', 'Українська'),
|
||||
'ur' => array('Urdu', /* Left-to-right marker "" */ 'اردو', LanguageInterface::DIRECTION_RTL),
|
||||
'vi' => array('Vietnamese', 'Tiếng Việt'),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\Core\Plugin\Context;
|
||||
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
use Drupal\Core\TypedData\TypedDataTrait;
|
||||
|
||||
/**
|
||||
|
@ -9,6 +10,8 @@ use Drupal\Core\TypedData\TypedDataTrait;
|
|||
*/
|
||||
class ContextDefinition implements ContextDefinitionInterface {
|
||||
|
||||
use DependencySerializationTrait;
|
||||
|
||||
use TypedDataTrait;
|
||||
|
||||
/**
|
||||
|
|
|
@ -419,9 +419,13 @@ class HtmlResponseAttachmentsProcessor implements AttachmentsResponseProcessorIn
|
|||
|
||||
if ($should_add_header) {
|
||||
// Also add a HTTP header "Link:".
|
||||
$href = '<' . Html::escape($attributes['href'] . '>');
|
||||
$href = '<' . Html::escape($attributes['href']) . '>';
|
||||
unset($attributes['href']);
|
||||
$attached['http_header'][] = ['Link', $href . drupal_http_header_attributes($attributes), TRUE];
|
||||
if ($param = drupal_http_header_attributes($attributes)) {
|
||||
$href .= ';' . $param;
|
||||
}
|
||||
|
||||
$attached['http_header'][] = ['Link', $href, FALSE];
|
||||
}
|
||||
}
|
||||
return $attached;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Core\StringTranslation\Translator;
|
||||
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* String translator using overrides from variables.
|
||||
|
@ -12,6 +13,8 @@ use Drupal\Core\Site\Settings;
|
|||
*/
|
||||
class CustomStrings extends StaticTranslation {
|
||||
|
||||
use DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* The settings read only object.
|
||||
*
|
||||
|
|
|
@ -77,6 +77,11 @@
|
|||
*/
|
||||
function searchHandler(event) {
|
||||
var options = autocomplete.options;
|
||||
|
||||
if (options.isComposing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var term = autocomplete.extractLastTerm(event.target.value);
|
||||
// Abort search if the first character is in firstCharacterBlacklist.
|
||||
if (term.length > 0 && options.firstCharacterBlacklist.indexOf(term[0]) !== -1) {
|
||||
|
@ -225,6 +230,14 @@
|
|||
.each(function () {
|
||||
$(this).data('ui-autocomplete')._renderItem = autocomplete.options.renderItem;
|
||||
});
|
||||
|
||||
// Use CompositionEvent to handle IME inputs. It requests remote server on "compositionend" event only.
|
||||
$autocomplete.on('compositionstart.autocomplete', function () {
|
||||
autocomplete.options.isComposing = true;
|
||||
});
|
||||
$autocomplete.on('compositionend.autocomplete', function () {
|
||||
autocomplete.options.isComposing = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
detach: function (context, settings, trigger) {
|
||||
|
@ -261,7 +274,9 @@
|
|||
renderItem: renderItem,
|
||||
minLength: 1,
|
||||
// Custom options, used by Drupal.autocomplete.
|
||||
firstCharacterBlacklist: ''
|
||||
firstCharacterBlacklist: '',
|
||||
// Custom options, indicate IME usage status.
|
||||
isComposing: false
|
||||
},
|
||||
ajax: {
|
||||
dataType: 'json'
|
||||
|
|
|
@ -151,7 +151,7 @@ function hook_block_view_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\B
|
|||
function hook_block_build_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
|
||||
// Add the 'user' cache context to some blocks.
|
||||
if ($some_condition) {
|
||||
$build['#contexts'][] = 'user';
|
||||
$build['#cache']['contexts'][] = 'user';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ class BookJavascriptTest extends JavascriptTestBase {
|
|||
$dragged->dragTo($target);
|
||||
|
||||
// Give javascript some time to manipulate the DOM.
|
||||
$this->getSession()->wait(1000, 'jQuery(".tabledrag-changed-warning").is(":visible")');
|
||||
$this->assertJsCondition('jQuery(".tabledrag-changed-warning").is(":visible")');
|
||||
|
||||
// Check that the 'unsaved changes' text appeared in the message area.
|
||||
$this->assertSession()->pageTextContains('You have unsaved changes.');
|
||||
|
|
|
@ -8,7 +8,6 @@ use Drupal\ckeditor\CKEditorPluginCssInterface;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageManager;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\editor\Entity\Editor;
|
||||
|
||||
/**
|
||||
|
@ -115,7 +114,7 @@ class Language extends CKEditorPluginBase implements CKEditorPluginConfigurableI
|
|||
],
|
||||
'#default_value' => $config['language_list'],
|
||||
'#description' => $this->t('The list of languages to show in the language dropdown. The basic list will only show the <a href=":url">six official languages of the UN</a>. The extended list will show all @count languages that are available in Drupal.', [
|
||||
':url' => Url::fromUri('http://www.un.org/en/aboutun/languages.shtml/')->toString(),
|
||||
':url' => 'https://www.un.org/en/sections/about-un/official-languages',
|
||||
'@count' => count($predefined_languages),
|
||||
]),
|
||||
'#attached' => ['library' => ['ckeditor/drupal.ckeditor.language.admin']],
|
||||
|
|
|
@ -7,6 +7,8 @@ source:
|
|||
constants:
|
||||
entity_type: node
|
||||
process:
|
||||
# If you are using this file to build a custom migration consider removing
|
||||
# the cid field to allow incremental migrations.
|
||||
cid: cid
|
||||
pid:
|
||||
plugin: migration
|
||||
|
|
|
@ -13,7 +13,10 @@ process:
|
|||
type: 'constants/type'
|
||||
'settings/comment_type': comment_type
|
||||
destination:
|
||||
plugin: md_entity:field_storage_config
|
||||
plugin: entity:field_storage_config
|
||||
dependencies:
|
||||
module:
|
||||
- comment
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d6_comment_type
|
||||
|
|
|
@ -7,6 +7,8 @@ source:
|
|||
constants:
|
||||
entity_type: node
|
||||
process:
|
||||
# If you are using this file to build a custom migration consider removing
|
||||
# the cid field to allow incremental migrations.
|
||||
cid: cid
|
||||
pid:
|
||||
plugin: migration
|
||||
|
|
|
@ -110,12 +110,13 @@ class CommentAccessControlHandler extends EntityAccessControlHandler {
|
|||
// access.
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
$is_name = $field_definition->getName() === 'name';
|
||||
/** @var \Drupal\comment\CommentInterface $entity */
|
||||
$entity = $items->getEntity();
|
||||
$commented_entity = $entity->getCommentedEntity();
|
||||
$anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous');
|
||||
$admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments');
|
||||
$anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT && $account->hasPermission('post comments'))
|
||||
$anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && ($anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT || $is_name) && $account->hasPermission('post comments'))
|
||||
->cachePerPermissions()
|
||||
->addCacheableDependency($entity)
|
||||
->addCacheableDependency($field_definition->getConfig($commented_entity->bundle()))
|
||||
|
|
|
@ -65,6 +65,16 @@ class CommentAnonymousTest extends CommentTestBase {
|
|||
$anonymous_comment1 = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName());
|
||||
$this->assertTrue($this->commentExists($anonymous_comment1), 'Anonymous comment without contact info found.');
|
||||
|
||||
// Ensure anonymous users cannot post in the name of registered users.
|
||||
$edit = array(
|
||||
'name' => $this->adminUser->getUsername(),
|
||||
'comment_body[0][value]' => $this->randomMachineName(),
|
||||
);
|
||||
$this->drupalPostForm('comment/reply/node/' . $this->node->id() . '/comment', $edit, t('Save'));
|
||||
$this->assertRaw(t('The name you used (%name) belongs to a registered user.', [
|
||||
'%name' => $this->adminUser->getUsername(),
|
||||
]));
|
||||
|
||||
// Allow contact info.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->setCommentAnonymous(COMMENT_ANONYMOUS_MAY_CONTACT);
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\config\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests draggable list builder.
|
||||
*
|
||||
* @group config
|
||||
*/
|
||||
class ConfigDraggableListBuilderTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('config_test');
|
||||
|
||||
/**
|
||||
* Test draggable lists.
|
||||
*/
|
||||
public function testDraggableList() {
|
||||
$this->drupalLogin($this->drupalCreateUser(array('administer permissions')));
|
||||
|
||||
// Create more than 50 roles.
|
||||
for ($i = 0; $i < 51; $i++) {
|
||||
$role = Role::create([
|
||||
'id' => 'role_' . $i,
|
||||
'label' => "Role $i",
|
||||
]);
|
||||
$role->save();
|
||||
}
|
||||
|
||||
// Navigate to Roles page
|
||||
$this->drupalGet('admin/people/roles');
|
||||
|
||||
// Test for the page title.
|
||||
$this->assertSession()->titleEquals(t('Roles') . ' | Drupal');
|
||||
|
||||
// Count the number of rows in table.
|
||||
$rows = $this->xpath('//form[@class="user-admin-roles-form"]/table/tbody/tr');
|
||||
$this->assertGreaterThan(50, count($rows));
|
||||
for ($i = 0; $i < 51; $i++) {
|
||||
$this->assertSession()->pageTextContains("Role $i");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -152,7 +152,6 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
$entity_type_id = $entity->getEntityTypeId();
|
||||
$entity_id = $entity->id();
|
||||
$entity_revision_id = $entity->getRevisionId();
|
||||
$entity_langcode = $entity->language()->getId();
|
||||
|
||||
$storage = $this->entityTypeManager->getStorage('content_moderation_state');
|
||||
$entities = $storage->loadByProperties([
|
||||
|
@ -174,11 +173,14 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
}
|
||||
|
||||
// Sync translations.
|
||||
if (!$content_moderation_state->hasTranslation($entity_langcode)) {
|
||||
$content_moderation_state->addTranslation($entity_langcode);
|
||||
}
|
||||
if ($content_moderation_state->language()->getId() !== $entity_langcode) {
|
||||
$content_moderation_state = $content_moderation_state->getTranslation($entity_langcode);
|
||||
if ($entity->getEntityType()->hasKey('langcode')) {
|
||||
$entity_langcode = $entity->language()->getId();
|
||||
if (!$content_moderation_state->hasTranslation($entity_langcode)) {
|
||||
$content_moderation_state->addTranslation($entity_langcode);
|
||||
}
|
||||
if ($content_moderation_state->language()->getId() !== $entity_langcode) {
|
||||
$content_moderation_state = $content_moderation_state->getTranslation($entity_langcode);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the ContentModerationState entity for the inserted entity.
|
||||
|
|
|
@ -292,8 +292,8 @@ class EntityTypeInfo implements ContainerInjectionInterface {
|
|||
|
||||
$fields = [];
|
||||
$fields['moderation_state'] = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(t('Moderation state'))
|
||||
->setDescription(t('The moderation state of this piece of content.'))
|
||||
->setLabel($this->t('Moderation state'))
|
||||
->setDescription($this->t('The moderation state of this piece of content.'))
|
||||
->setComputed(TRUE)
|
||||
->setClass(ModerationStateFieldItemList::class)
|
||||
->setSetting('target_type', 'moderation_state')
|
||||
|
@ -310,6 +310,7 @@ class EntityTypeInfo implements ContainerInjectionInterface {
|
|||
->addConstraint('ModerationState', [])
|
||||
->setDisplayConfigurable('form', FALSE)
|
||||
->setDisplayConfigurable('view', FALSE)
|
||||
->setReadOnly(FALSE)
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
return $fields;
|
||||
|
|
|
@ -43,12 +43,14 @@ class ModerationStateFieldItemList extends EntityReferenceFieldItemList {
|
|||
->loadRevision($revision_to_load);
|
||||
|
||||
// Return the correct translation.
|
||||
$langcode = $entity->language()->getId();
|
||||
if (!$content_moderation_state->hasTranslation($langcode)) {
|
||||
$content_moderation_state->addTranslation($langcode);
|
||||
}
|
||||
if ($content_moderation_state->language()->getId() !== $langcode) {
|
||||
$content_moderation_state = $content_moderation_state->getTranslation($langcode);
|
||||
if ($entity->getEntityType()->hasKey('langcode')) {
|
||||
$langcode = $entity->language()->getId();
|
||||
if (!$content_moderation_state->hasTranslation($langcode)) {
|
||||
$content_moderation_state->addTranslation($langcode);
|
||||
}
|
||||
if ($content_moderation_state->language()->getId() !== $langcode) {
|
||||
$content_moderation_state = $content_moderation_state->getTranslation($langcode);
|
||||
}
|
||||
}
|
||||
|
||||
return $content_moderation_state->get('moderation_state')->entity;
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace Drupal\Tests\content_moderation\Kernel;
|
|||
|
||||
use Drupal\content_moderation\Entity\ContentModerationState;
|
||||
use Drupal\content_moderation\Entity\ModerationState;
|
||||
use Drupal\entity_test\Entity\EntityTestBundle;
|
||||
use Drupal\entity_test\Entity\EntityTestWithBundle;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
@ -21,12 +23,14 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'entity_test',
|
||||
'node',
|
||||
'content_moderation',
|
||||
'user',
|
||||
'system',
|
||||
'language',
|
||||
'content_translation',
|
||||
'text',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -38,6 +42,7 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
$this->installSchema('node', 'node_access');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('entity_test_with_bundle');
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
$this->installConfig('content_moderation');
|
||||
}
|
||||
|
@ -210,6 +215,91 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
$this->assertEquals(6, $english_node->getRevisionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a non-translatable entity type with a langcode can be moderated.
|
||||
*/
|
||||
public function testNonTranslatableEntityTypeModeration() {
|
||||
// Make the 'entity_test_with_bundle' entity type revisionable.
|
||||
$entity_type = clone \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle');
|
||||
$keys = $entity_type->getKeys();
|
||||
$keys['revision'] = 'revision_id';
|
||||
$entity_type->set('entity_keys', $keys);
|
||||
\Drupal::state()->set('entity_test_with_bundle.entity_type', $entity_type);
|
||||
\Drupal::entityDefinitionUpdateManager()->applyUpdates();
|
||||
|
||||
// Create a test bundle.
|
||||
$entity_test_bundle = EntityTestBundle::create([
|
||||
'id' => 'example',
|
||||
]);
|
||||
$entity_test_bundle->setThirdPartySetting('content_moderation', 'enabled', TRUE);
|
||||
$entity_test_bundle->setThirdPartySetting('content_moderation', 'allowed_moderation_states', [
|
||||
'draft',
|
||||
'published'
|
||||
]);
|
||||
$entity_test_bundle->setThirdPartySetting('content_moderation', 'default_moderation_state', 'draft');
|
||||
$entity_test_bundle->save();
|
||||
|
||||
// Check that the tested entity type is not translatable.
|
||||
$entity_type = \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle');
|
||||
$this->assertFalse($entity_type->isTranslatable(), 'The test entity type is not translatable.');
|
||||
|
||||
// Create a test entity.
|
||||
$entity_test_with_bundle = EntityTestWithBundle::create([
|
||||
'type' => 'example'
|
||||
]);
|
||||
$entity_test_with_bundle->save();
|
||||
$this->assertEquals('draft', $entity_test_with_bundle->moderation_state->entity->id());
|
||||
|
||||
$entity_test_with_bundle->moderation_state->target_id = 'published';
|
||||
$entity_test_with_bundle->save();
|
||||
|
||||
$this->assertEquals('published', EntityTestWithBundle::load($entity_test_with_bundle->id())->moderation_state->entity->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a non-translatable entity type without a langcode can be
|
||||
* moderated.
|
||||
*/
|
||||
public function testNonLangcodeEntityTypeModeration() {
|
||||
// Make the 'entity_test_with_bundle' entity type revisionable and unset
|
||||
// the langcode entity key.
|
||||
$entity_type = clone \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle');
|
||||
$keys = $entity_type->getKeys();
|
||||
$keys['revision'] = 'revision_id';
|
||||
unset($keys['langcode']);
|
||||
$entity_type->set('entity_keys', $keys);
|
||||
\Drupal::state()->set('entity_test_with_bundle.entity_type', $entity_type);
|
||||
\Drupal::entityDefinitionUpdateManager()->applyUpdates();
|
||||
|
||||
// Create a test bundle.
|
||||
$entity_test_bundle = EntityTestBundle::create([
|
||||
'id' => 'example',
|
||||
]);
|
||||
$entity_test_bundle->setThirdPartySetting('content_moderation', 'enabled', TRUE);
|
||||
$entity_test_bundle->setThirdPartySetting('content_moderation', 'allowed_moderation_states', [
|
||||
'draft',
|
||||
'published'
|
||||
]);
|
||||
$entity_test_bundle->setThirdPartySetting('content_moderation', 'default_moderation_state', 'draft');
|
||||
$entity_test_bundle->save();
|
||||
|
||||
// Check that the tested entity type is not translatable.
|
||||
$entity_type = \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle');
|
||||
$this->assertFalse($entity_type->isTranslatable(), 'The test entity type is not translatable.');
|
||||
|
||||
// Create a test entity.
|
||||
$entity_test_with_bundle = EntityTestWithBundle::create([
|
||||
'type' => 'example'
|
||||
]);
|
||||
$entity_test_with_bundle->save();
|
||||
$this->assertEquals('draft', $entity_test_with_bundle->moderation_state->entity->id());
|
||||
|
||||
$entity_test_with_bundle->moderation_state->target_id = 'published';
|
||||
$entity_test_with_bundle->save();
|
||||
|
||||
$this->assertEquals('published', EntityTestWithBundle::load($entity_test_with_bundle->id())->moderation_state->entity->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the node after clearing the static cache.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
use Drupal\content_moderation\Entity\Handler\ModerationHandler;
|
||||
use Drupal\content_moderation\EntityTypeInfo;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\content_moderation\EntityTypeInfo
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class EntityTypeInfoTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'content_moderation',
|
||||
'entity_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity type info class.
|
||||
*
|
||||
* @var \Drupal\content_moderation\EntityTypeInfo
|
||||
*/
|
||||
protected $entityTypeInfo;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->entityTypeInfo = $this->container->get('class_resolver')->getInstanceFromDefinition(EntityTypeInfo::class);
|
||||
$this->entityTypeManager = $this->container->get('entity_type.manager');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::entityBaseFieldInfo
|
||||
*/
|
||||
public function testEntityBaseFieldInfo() {
|
||||
$definition = $this->entityTypeManager->getDefinition('entity_test');
|
||||
$definition->setHandlerClass('moderation', ModerationHandler::class);
|
||||
|
||||
$base_fields = $this->entityTypeInfo->entityBaseFieldInfo($definition);
|
||||
|
||||
$this->assertFalse($base_fields['moderation_state']->isReadOnly());
|
||||
$this->assertTrue($base_fields['moderation_state']->isComputed());
|
||||
$this->assertTrue($base_fields['moderation_state']->isTranslatable());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\datetime\Kernel;
|
||||
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests serializing a form with an injected datetime instance.
|
||||
*
|
||||
* @group datetime
|
||||
*/
|
||||
class DateTimeFormInjectionTest extends KernelTestBase implements FormInterface {
|
||||
|
||||
use DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* A Dblog logger instance.
|
||||
*
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['system', 'datetime'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', ['key_value_expire', 'sequences']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'datetime_test_injection_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* Process callback.
|
||||
*
|
||||
* @param array $element
|
||||
* Form element.
|
||||
*
|
||||
* @return array
|
||||
* Processed element.
|
||||
*/
|
||||
public function process($element) {
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['datelist_element'] = [
|
||||
'#title' => 'datelist test',
|
||||
'#type' => 'datelist',
|
||||
'#default_value' => new DrupalDateTime('2000-01-01 00:00:00'),
|
||||
'#date_part_order' => [
|
||||
'month',
|
||||
'day',
|
||||
'year',
|
||||
'hour',
|
||||
'minute', 'ampm',
|
||||
],
|
||||
'#date_text_parts' => ['year'],
|
||||
'#date_year_range' => '2010:2020',
|
||||
'#date_increment' => 15,
|
||||
];
|
||||
$form['#process'][] = [$this, 'process'];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->assertTrue(TRUE);
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests custom string injection serialization.
|
||||
*/
|
||||
public function testDatetimeSerialization() {
|
||||
$form_state = new FormState();
|
||||
$form_state->setRequestMethod('POST');
|
||||
$form_state->setCached();
|
||||
$form_builder = $this->container->get('form_builder');
|
||||
$form_id = $form_builder->getFormId($this, $form_state);
|
||||
$form = $form_builder->retrieveForm($form_id, $form_state);
|
||||
$form_builder->prepareForm($form_id, $form, $form_state);
|
||||
$form_builder->processForm($form_id, $form, $form_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -123,4 +123,4 @@ process:
|
|||
- '@type'
|
||||
- global_settings
|
||||
destination:
|
||||
plugin: md_entity:field_storage_config
|
||||
plugin: entity:field_storage_config
|
||||
|
|
|
@ -22,6 +22,7 @@ process:
|
|||
datestamp: datetime
|
||||
datetime: datetime
|
||||
email: email
|
||||
entityreference: entity_reference
|
||||
file: file
|
||||
image: image
|
||||
link_field: link
|
||||
|
|
|
@ -51,7 +51,7 @@ process:
|
|||
-
|
||||
plugin: static_map
|
||||
bypass: true
|
||||
source: type
|
||||
source: formatter_type
|
||||
map:
|
||||
date_default: datetime_default
|
||||
email_default: email_mailto
|
||||
|
@ -61,6 +61,9 @@ process:
|
|||
link_default: link
|
||||
phone: basic_string
|
||||
taxonomy_term_reference_link: entity_reference_label
|
||||
entityreference_label: entity_reference_label
|
||||
entityreference_entity_id: entity_reference_entity_id
|
||||
entityreference_entity_view: entity_reference_entity_view
|
||||
-
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
|
|
|
@ -21,6 +21,7 @@ process:
|
|||
source:
|
||||
- instance_settings
|
||||
- widget_settings
|
||||
- field_settings
|
||||
default_value_function: ''
|
||||
default_value:
|
||||
plugin: d7_field_instance_defaults
|
||||
|
|
|
@ -46,6 +46,7 @@ process:
|
|||
phone_textfield: telephone_default
|
||||
options_onoff: boolean_checkbox
|
||||
entityreference_autocomplete: entity_reference_autocomplete
|
||||
entityreference_autocomplete_tags: entity_reference_autocomplete_tags
|
||||
taxonomy_autocomplete: entity_reference_autocomplete
|
||||
'options/settings':
|
||||
plugin: field_instance_widget_settings
|
||||
|
|
|
@ -17,9 +17,38 @@ class FieldInstanceSettings extends ProcessPluginBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($instance_settings, $widget_settings) = $value;
|
||||
list($instance_settings, $widget_settings, $field_settings) = $value;
|
||||
$widget_type = $widget_settings['type'];
|
||||
|
||||
// Get entityreference handler settings from source field configuration.
|
||||
if ($row->getSourceProperty('type') == "entityreference") {
|
||||
$instance_settings['handler'] = 'default:' . $field_settings['target_type'];
|
||||
// Transform the sort settings to D8 structure.
|
||||
$sort = [
|
||||
'field' => '_none',
|
||||
'direction' => 'ASC',
|
||||
];
|
||||
if (!empty(array_filter($field_settings['handler_settings']['sort']))) {
|
||||
if ($field_settings['handler_settings']['sort']['type'] == "property") {
|
||||
$sort = [
|
||||
'field' => $field_settings['handler_settings']['sort']['property'],
|
||||
'direction' => $field_settings['handler_settings']['sort']['direction'],
|
||||
];
|
||||
}
|
||||
elseif ($field_settings['handler_settings']['sort']['type'] == "field") {
|
||||
$sort = [
|
||||
'field' => $field_settings['handler_settings']['sort']['field'],
|
||||
'direction' => $field_settings['handler_settings']['sort']['direction'],
|
||||
];
|
||||
}
|
||||
}
|
||||
if (empty($field_settings['handler_settings']['target_bundles'])) {
|
||||
$field_settings['handler_settings']['target_bundles'] = NULL;
|
||||
}
|
||||
$field_settings['handler_settings']['sort'] = $sort;
|
||||
$instance_settings['handler_settings'] = $field_settings['handler_settings'];
|
||||
}
|
||||
|
||||
switch ($widget_type) {
|
||||
case 'image_image':
|
||||
$settings = $instance_settings;
|
||||
|
|
|
@ -28,6 +28,7 @@ class FieldInstance extends DrupalSqlBase {
|
|||
->fields('fc', array('type'));
|
||||
|
||||
$query->innerJoin('field_config', 'fc', 'fci.field_id = fc.id');
|
||||
$query->addField('fc', 'data', 'field_data');
|
||||
|
||||
// Optionally filter by entity type and bundle.
|
||||
if (isset($this->configuration['entity_type'])) {
|
||||
|
@ -53,6 +54,7 @@ class FieldInstance extends DrupalSqlBase {
|
|||
'instance_settings' => $this->t('Field instance settings.'),
|
||||
'widget_settings' => $this->t('Widget settings.'),
|
||||
'display_settings' => $this->t('Display settings.'),
|
||||
'field_settings' => $this->t('Field settings.'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -81,6 +83,9 @@ class FieldInstance extends DrupalSqlBase {
|
|||
// This is for parity with the d6_field_instance plugin.
|
||||
$row->setSourceProperty('widget_type', $data['widget']['type']);
|
||||
|
||||
$field_data = unserialize($row->getSourceProperty('field_data'));
|
||||
$row->setSourceProperty('field_settings', $field_data['settings']);
|
||||
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,15 @@ class FieldInstancePerViewMode extends DrupalSqlBase {
|
|||
$data = unserialize($field_instance['data']);
|
||||
// We don't need to include the serialized data in the returned rows.
|
||||
unset($field_instance['data']);
|
||||
|
||||
foreach ($data['display'] as $view_mode => $info) {
|
||||
$rows[] = array_merge($field_instance, $info, array('view_mode' => $view_mode));
|
||||
// Rename type to formatter_type in the info array.
|
||||
$info['formatter_type'] = $info['type'];
|
||||
unset($info['type']);
|
||||
|
||||
$rows[] = array_merge($field_instance, $info, [
|
||||
'view_mode' => $view_mode,
|
||||
]);
|
||||
}
|
||||
}
|
||||
return new \ArrayIterator($rows);
|
||||
|
@ -35,8 +42,11 @@ class FieldInstancePerViewMode extends DrupalSqlBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('field_config_instance', 'fci')
|
||||
->fields('fci', array('entity_type', 'bundle', 'field_name', 'data'));
|
||||
$query = $this->select('field_config_instance', 'fci')
|
||||
->fields('fci', ['entity_type', 'bundle', 'field_name', 'data'])
|
||||
->fields('fc', ['type']);
|
||||
$query->join('field_config', 'fc', 'fc.field_name = fci.field_name');
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,7 +59,8 @@ class FieldInstancePerViewMode extends DrupalSqlBase {
|
|||
'field_name' => $this->t('Machine name of the field.'),
|
||||
'view_mode' => $this->t('The original machine name of the view mode.'),
|
||||
'label' => $this->t('The display label of the field.'),
|
||||
'type' => $this->t('The formatter ID.'),
|
||||
'type' => $this->t('The field ID.'),
|
||||
'formatter_type' => $this->t('The formatter ID.'),
|
||||
'settings' => $this->t('Array of formatter-specific settings.'),
|
||||
'module' => $this->t('The module providing the formatter.'),
|
||||
'weight' => $this->t('Display weight of the field.'),
|
||||
|
|
|
@ -20,7 +20,12 @@ class BooleanFieldTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_test', 'field_ui', 'options');
|
||||
public static $modules = [
|
||||
'entity_test',
|
||||
'field_ui',
|
||||
'options',
|
||||
'field_test_boolean_access_denied',
|
||||
];
|
||||
|
||||
/**
|
||||
* A field to use in this test class.
|
||||
|
@ -179,4 +184,66 @@ class BooleanFieldTest extends WebTestBase {
|
|||
$this->assertFieldById('edit-settings-off-label', $off);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test field access.
|
||||
*/
|
||||
public function testFormAccess() {
|
||||
$on = 'boolean_on';
|
||||
$off = 'boolean_off';
|
||||
$label = 'boolean_label';
|
||||
$field_name = 'boolean_name';
|
||||
$this->fieldStorage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'boolean',
|
||||
]);
|
||||
$this->fieldStorage->save();
|
||||
$this->field = FieldConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'bundle' => 'entity_test',
|
||||
'label' => $label,
|
||||
'settings' => [
|
||||
'on_label' => $on,
|
||||
'off_label' => $off,
|
||||
],
|
||||
]);
|
||||
$this->field->save();
|
||||
|
||||
// Create a form display for the default form mode.
|
||||
entity_get_form_display('entity_test', 'entity_test', 'default')
|
||||
->setComponent($field_name, [
|
||||
'type' => 'boolean_checkbox',
|
||||
])
|
||||
->save();
|
||||
|
||||
// Create a display for the full view mode.
|
||||
entity_get_display('entity_test', 'entity_test', 'full')
|
||||
->setComponent($field_name, [
|
||||
'type' => 'boolean',
|
||||
])
|
||||
->save();
|
||||
|
||||
// Display creation form.
|
||||
$this->drupalGet('entity_test/add');
|
||||
$this->assertFieldByName("{$field_name}[value]");
|
||||
|
||||
// Should be posted OK.
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
|
||||
$id = $match[1];
|
||||
$this->assertText(t('entity_test @id has been created.', ['@id' => $id]));
|
||||
|
||||
// Tell the test module to disable access to the field.
|
||||
\Drupal::state()->set('field.test_boolean_field_access_field', $field_name);
|
||||
$this->drupalGet('entity_test/add');
|
||||
// Field should not be there anymore.
|
||||
$this->assertNoFieldByName("{$field_name}[value]");
|
||||
// Should still be able to post the form.
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
|
||||
$id = $match[1];
|
||||
$this->assertText(t('entity_test @id has been created.', ['@id' => $id]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\field_test\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
use Drupal\Core\Field\FieldItemBase;
|
||||
|
||||
/**
|
||||
* Defines the 'test_object_field' entity field item.
|
||||
*
|
||||
* @FieldType(
|
||||
* id = "test_object_field",
|
||||
* label = @Translation("Test object field"),
|
||||
* description = @Translation("Test field type that has an object to test serialization"),
|
||||
* default_widget = "test_object_field_widget",
|
||||
* default_formatter = "object_field_test_default"
|
||||
* )
|
||||
*/
|
||||
class TestObjectItem extends FieldItemBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
|
||||
$properties['value'] = DataDefinition::create('any')
|
||||
->setLabel(t('Value'))
|
||||
->setRequired(TRUE);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function schema(FieldStorageDefinitionInterface $field_definition) {
|
||||
return [
|
||||
'columns' => [
|
||||
'value' => [
|
||||
'description' => 'The object item value.',
|
||||
'type' => 'blob',
|
||||
'not null' => TRUE,
|
||||
'serialize' => TRUE,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setValue($values, $notify = TRUE) {
|
||||
if (isset($values['value'])) {
|
||||
// @todo Remove this in https://www.drupal.org/node/2788637.
|
||||
if (is_string($values['value'])) {
|
||||
$values['value'] = unserialize($values['value']);
|
||||
}
|
||||
}
|
||||
parent::setValue($values, $notify);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
name: 'Boolean field Test'
|
||||
type: module
|
||||
description: 'Support module for the field and entity display tests.'
|
||||
core: 8.x
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- field
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Module for testing denying access to boolean fields.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_field_access().
|
||||
*/
|
||||
function field_test_boolean_access_denied_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
|
||||
return AccessResult::forbiddenIf($field_definition->getName() === \Drupal::state()->get('field.test_boolean_field_access_field'));
|
||||
}
|
|
@ -277,6 +277,49 @@ class EntityReferenceFormatterTest extends EntityKernelTestBase {
|
|||
$this->assertEqual($actual_occurrences, $expected_occurrences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the same entity referenced from different places.
|
||||
*/
|
||||
public function testEntityReferenceRecursiveProtectionWithManyRenderedEntities() {
|
||||
$formatter = 'entity_reference_entity_view';
|
||||
$view_builder = $this->entityManager->getViewBuilder($this->entityType);
|
||||
|
||||
// Set the default view mode to use the 'entity_reference_entity_view'
|
||||
// formatter.
|
||||
entity_get_display($this->entityType, $this->bundle, 'default')
|
||||
->setComponent($this->fieldName, [
|
||||
'type' => $formatter,
|
||||
])
|
||||
->save();
|
||||
|
||||
$storage = $this->entityManager->getStorage($this->entityType);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $referenced_entity */
|
||||
$referenced_entity = $storage->create(['name' => $this->randomMachineName()]);
|
||||
|
||||
$range = range(0, 30);
|
||||
$referencing_entities = array_map(function () use ($storage, $referenced_entity) {
|
||||
$referencing_entity = $storage->create([
|
||||
'name' => $this->randomMachineName(),
|
||||
$this->fieldName => $referenced_entity,
|
||||
]);
|
||||
$referencing_entity->save();
|
||||
return $referencing_entity;
|
||||
}, $range);
|
||||
|
||||
$build = $view_builder->viewMultiple($referencing_entities, 'default');
|
||||
$output = $this->render($build);
|
||||
|
||||
// The title of entity_test entities is printed twice by default, so we have
|
||||
// to multiply the formatter's recursive rendering protection limit by 2.
|
||||
// Additionally, we have to take into account 2 additional occurrences of
|
||||
// the entity title because we're rendering the full entity, not just the
|
||||
// reference field.
|
||||
$expected_occurrences = 30 * 2 + 2;
|
||||
$actual_occurrences = substr_count($output, $referenced_entity->get('name')->value);
|
||||
$this->assertEquals($expected_occurrences, $actual_occurrences);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the label formatter.
|
||||
*/
|
||||
|
|
|
@ -276,6 +276,9 @@ class MigrateFieldFormatterSettingsTest extends MigrateDrupal7TestBase {
|
|||
$this->assertComponent('node.test_content_type.default', 'field_text_list', 'list_default', 'above', 10);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_integer_list', 'list_default', 'above', 11);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_long_text', 'text_default', 'above', 12);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_node_entityreference', 'entity_reference_label', 'above', 15);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_user_entityreference', 'entity_reference_label', 'above', 16);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_term_entityreference', 'entity_reference_label', 'above', 17);
|
||||
$this->assertComponentNotExists('node.test_content_type.default', 'field_term_reference');
|
||||
$this->assertComponentNotExists('node.test_content_type.default', 'field_text');
|
||||
|
||||
|
|
|
@ -141,6 +141,9 @@ class MigrateFieldInstanceTest extends MigrateDrupal7TestBase {
|
|||
$this->assertEntity('node.test_content_type.field_integer_list', 'Integer List', 'list_integer', FALSE);
|
||||
$this->assertEntity('node.test_content_type.field_long_text', 'Long text', 'text_with_summary', FALSE);
|
||||
$this->assertEntity('node.test_content_type.field_term_reference', 'Term Reference', 'entity_reference', FALSE);
|
||||
$this->assertEntity('node.test_content_type.field_node_entityreference', 'Node Entity Reference', 'entity_reference', FALSE);
|
||||
$this->assertEntity('node.test_content_type.field_user_entityreference', 'User Entity Reference', 'entity_reference', FALSE);
|
||||
$this->assertEntity('node.test_content_type.field_term_entityreference', 'Term Entity Reference', 'entity_reference', FALSE);
|
||||
$this->assertEntity('node.test_content_type.field_text', 'Text', 'text', FALSE);
|
||||
$this->assertEntity('comment.comment_node_test_content_type.field_integer', 'Integer', 'integer', FALSE);
|
||||
$this->assertEntity('user.user.field_file', 'File', 'file', FALSE);
|
||||
|
|
|
@ -125,6 +125,9 @@ class MigrateFieldInstanceWidgetSettingsTest extends MigrateDrupal7TestBase {
|
|||
$this->assertComponent('node.test_content_type.default', 'field_long_text', 'text_textarea_with_summary', 13);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_phone', 'telephone_default', 6);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_term_reference', 'entity_reference_autocomplete', 14);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_node_entityreference', 'entity_reference_autocomplete', 16);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_user_entityreference', 'options_buttons', 17);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_term_entityreference', 'entity_reference_autocomplete_tags', 18);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_text', 'text_textfield', 15);
|
||||
$this->assertComponent('node.test_content_type.default', 'field_text_list', 'options_select', 11);
|
||||
|
||||
|
|
|
@ -100,6 +100,9 @@ class MigrateFieldTest extends MigrateDrupal7TestBase {
|
|||
$this->assertEntity('node.field_phone', 'telephone', FALSE, 1);
|
||||
$this->assertEntity('node.field_date', 'datetime', FALSE, 1);
|
||||
$this->assertEntity('node.field_date_with_end_time', 'datetime', FALSE, 1);
|
||||
$this->assertEntity('node.field_node_entityreference', 'entity_reference', FALSE, -1);
|
||||
$this->assertEntity('node.field_user_entityreference', 'entity_reference', FALSE, 1);
|
||||
$this->assertEntity('node.field_term_entityreference', 'entity_reference', FALSE, -1);
|
||||
|
||||
// Assert that the taxonomy term reference fields are referencing the
|
||||
// correct entity type.
|
||||
|
@ -108,6 +111,15 @@ class MigrateFieldTest extends MigrateDrupal7TestBase {
|
|||
$field = FieldStorageConfig::load('node.taxonomy_forums');
|
||||
$this->assertIdentical('taxonomy_term', $field->getSetting('target_type'));
|
||||
|
||||
// Assert that the entityreference fields are referencing the correct
|
||||
// entity type.
|
||||
$field = FieldStorageConfig::load('node.field_node_entityreference');
|
||||
$this->assertIdentical('node', $field->getSetting('target_type'));
|
||||
$field = FieldStorageConfig::load('node.field_user_entityreference');
|
||||
$this->assertIdentical('user', $field->getSetting('target_type'));
|
||||
$field = FieldStorageConfig::load('node.field_term_entityreference');
|
||||
$this->assertIdentical('taxonomy_term', $field->getSetting('target_type'));
|
||||
|
||||
// Validate that the source count and processed count match up.
|
||||
/** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
|
||||
$migration = $this->getMigration('d7_field');
|
||||
|
|
|
@ -41,6 +41,24 @@ class FieldInstancePerViewModeTest extends MigrateSqlSourceTestBase {
|
|||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['field_config'] = [
|
||||
[
|
||||
'id' => '2',
|
||||
'field_name' => 'body',
|
||||
'type' => 'text_with_summary',
|
||||
'module' => 'text',
|
||||
'active' => '1',
|
||||
'storage_type' => 'field_sql_storage',
|
||||
'storage_module' => 'field_sql_storage',
|
||||
'storage_active' => '1',
|
||||
'locked' => '0',
|
||||
'data' => 'a:7:{s:12:"entity_types";a:1:{i:0;s:4:"node";}s:7:"indexes";a:1:{s:6:"format";a:1:{i:0;s:6:"format";}}s:8:"settings";a:0:{}s:12:"translatable";i:0;s:12:"foreign keys";a:1:{s:6:"format";a:2:{s:5:"table";s:13:"filter_format";s:7:"columns";a:1:{s:6:"format";s:6:"format";}}}s:7:"storage";a:4:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";}s:2:"id";s:2:"25";}',
|
||||
'cardinality' => '1',
|
||||
'translatable' => '0',
|
||||
'deleted' => '0',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
|
@ -48,7 +66,8 @@ class FieldInstancePerViewModeTest extends MigrateSqlSourceTestBase {
|
|||
'bundle' => 'page',
|
||||
'field_name' => 'body',
|
||||
'label' => 'hidden',
|
||||
'type' => 'text_default',
|
||||
'type' => 'text_with_summary',
|
||||
'formatter_type' => 'text_default',
|
||||
'settings' => [],
|
||||
'module' => 'text',
|
||||
'weight' => 0,
|
||||
|
@ -59,7 +78,8 @@ class FieldInstancePerViewModeTest extends MigrateSqlSourceTestBase {
|
|||
'bundle' => 'page',
|
||||
'field_name' => 'body',
|
||||
'label' => 'hidden',
|
||||
'type' => 'text_summary_or_trimmed',
|
||||
'type' => 'text_with_summary',
|
||||
'formatter_type' => 'text_summary_or_trimmed',
|
||||
'settings' => [
|
||||
'trim_length' => 600,
|
||||
],
|
||||
|
|
30
core/modules/field/tests/src/Kernel/String/UuidItemTest.php
Normal file
30
core/modules/field/tests/src/Kernel/String/UuidItemTest.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel\String;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\Tests\field\Kernel\FieldKernelTestBase;
|
||||
use Drupal\Component\Uuid\Uuid;
|
||||
|
||||
/**
|
||||
* Tests the UUID field.
|
||||
*
|
||||
* @group field
|
||||
*/
|
||||
class UuidItemTest extends FieldKernelTestBase {
|
||||
|
||||
/**
|
||||
* Tests 'uuid' random values.
|
||||
*/
|
||||
public function testSampleValue() {
|
||||
$entity = EntityTest::create([]);
|
||||
$entity->save();
|
||||
|
||||
$uuid_field = $entity->get('uuid');
|
||||
|
||||
// Test the generateSampleValue() method.
|
||||
$uuid_field->generateSampleItems();
|
||||
$this->assertTrue(Uuid::isValid($uuid_field->value));
|
||||
}
|
||||
|
||||
}
|
59
core/modules/field/tests/src/Kernel/TestObjectItemTest.php
Normal file
59
core/modules/field/tests/src/Kernel/TestObjectItemTest.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Tests the serialization of an object.
|
||||
*
|
||||
* @group field
|
||||
*/
|
||||
class TestObjectItemTest extends FieldKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('field_test');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a 'test_field' field and storage for validation.
|
||||
FieldStorageConfig::create(array(
|
||||
'field_name' => 'field_test',
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'test_object_field',
|
||||
))->save();
|
||||
FieldConfig::create([
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'field_test',
|
||||
'bundle' => 'entity_test',
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the serialization of a field type that has an object.
|
||||
*/
|
||||
public function testTestObjectItem() {
|
||||
$object = new \stdClass();
|
||||
$object->foo = 'bar';
|
||||
$entity = EntityTest::create();
|
||||
$entity->field_test->value = $object;
|
||||
$entity->save();
|
||||
|
||||
// Verify that the entity has been created properly.
|
||||
$id = $entity->id();
|
||||
$entity = EntityTest::load($id);
|
||||
$this->assertTrue($entity->field_test->value instanceof \stdClass);
|
||||
$this->assertEquals($object, $entity->field_test->value);
|
||||
}
|
||||
|
||||
}
|
|
@ -28,7 +28,7 @@ class FieldInstanceSettingsTest extends MigrateTestCase {
|
|||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$value = $plugin->transform([[], ['type' => 'image_image']], $executable, $row, 'foo');
|
||||
$value = $plugin->transform([[], ['type' => 'image_image'], []], $executable, $row, 'foo');
|
||||
$this->assertInternalType('array', $value['default_image']);
|
||||
$this->assertSame('', $value['default_image']['alt']);
|
||||
$this->assertSame('', $value['default_image']['title']);
|
||||
|
|
|
@ -13,6 +13,9 @@ source:
|
|||
# configuration in this migration's process pipeline as an example.
|
||||
source_base_path: ''
|
||||
process:
|
||||
# If you are using both this migration and d6_user_picture_file in a custom
|
||||
# migration and executing migrations incrementally, it is recommended that
|
||||
# you remove the fid mapping here to avoid potential ID conflicts.
|
||||
fid: fid
|
||||
filename: filename
|
||||
source_full_path:
|
||||
|
|
|
@ -20,4 +20,7 @@ process:
|
|||
cardinality: 'constants/cardinality'
|
||||
'settings/display_field': 'constants/display_field'
|
||||
destination:
|
||||
plugin: md_entity:field_storage_config
|
||||
plugin: entity:field_storage_config
|
||||
dependencies:
|
||||
module:
|
||||
- file
|
||||
|
|
|
@ -13,6 +13,8 @@ source:
|
|||
# configuration in this migration's process pipeline as an example.
|
||||
source_base_path: ''
|
||||
process:
|
||||
# If you are using this file to build a custom migration consider removing
|
||||
# the fid field to allow incremental migrations.
|
||||
fid: fid
|
||||
filename: filename
|
||||
source_full_path:
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace Drupal\file\Plugin\migrate\process\d6;
|
|||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
use Drupal\migrate\Plugin\MigrateProcessInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
@ -76,18 +75,7 @@ class CckFile extends ProcessPluginBase implements ContainerFactoryPluginInterfa
|
|||
// some reason -- file migration is notoriously brittle -- and we do NOT
|
||||
// want to send invalid file references into the field system (it causes
|
||||
// fatals), so return an empty item instead.
|
||||
try {
|
||||
$fid = $this->migrationPlugin->transform($value['fid'], $migrate_executable, $row, $destination_property);
|
||||
}
|
||||
// If the migration plugin completely fails its lookup process, it will
|
||||
// throw a MigrateSkipRowException. It shouldn't, but that is being dealt
|
||||
// with at https://www.drupal.org/node/2487568. Until that lands, return
|
||||
// an empty item.
|
||||
catch (MigrateSkipRowException $e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($fid) {
|
||||
if ($fid = $this->migrationPlugin->transform($value['fid'], $migrate_executable, $row, $destination_property)) {
|
||||
return [
|
||||
'target_id' => $fid,
|
||||
'display' => $value['list'],
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Block;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Block\BlockResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockHalJsonAnonTest extends BlockResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Block;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Block\BlockResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockHalJsonBasicAuthTest extends BlockResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Block;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Block\BlockResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockHalJsonCookieTest extends BlockResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Comment;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class CommentHalJsonAnonTest extends CommentHalJsonTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Anononymous users cannot edit their own comments.
|
||||
*
|
||||
* @see \Drupal\comment\CommentAccessControlHandler::checkAccess
|
||||
*
|
||||
* Therefore we grant them the 'administer comments' permission for the
|
||||
* purpose of this test. Then they are able to edit their own comments, but
|
||||
* some fields are still not editable, even with that permission.
|
||||
*
|
||||
* @see ::setUpAuthorization
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'changed',
|
||||
'thread',
|
||||
'entity_type',
|
||||
'field_name',
|
||||
'entity_id',
|
||||
];
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Comment;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class CommentHalJsonBasicAuthTest extends CommentHalJsonTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Comment;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class CommentHalJsonCookieTest extends CommentHalJsonTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Comment;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Comment\CommentResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
abstract class CommentHalJsonTestBase extends CommentResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* The HAL+JSON format causes different PATCH-protected fields. For some
|
||||
* reason, the 'pid' and 'homepage' fields are NOT PATCH-protected, even
|
||||
* though they are for non-HAL+JSON serializations.
|
||||
*
|
||||
* @todo fix in https://www.drupal.org/node/2824271
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'created',
|
||||
'changed',
|
||||
'status',
|
||||
'thread',
|
||||
'entity_type',
|
||||
'field_name',
|
||||
'entity_id',
|
||||
'uid',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
|
||||
// Because \Drupal\comment\Entity\Comment::getOwner() generates an in-memory
|
||||
// User entity without a UUID, we cannot use it.
|
||||
$author = User::load($this->entity->getOwnerId());
|
||||
$commented_entity = EntityTest::load(1);
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/comment/1?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/comment/comment',
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/comment/comment/entity_id' => [
|
||||
[
|
||||
'href' => $this->baseUrl . '/entity_test/1?_format=hal_json',
|
||||
],
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/comment/comment/uid' => [
|
||||
[
|
||||
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
|
||||
'lang' => 'en',
|
||||
],
|
||||
],
|
||||
],
|
||||
'_embedded' => [
|
||||
$this->baseUrl . '/rest/relation/comment/comment/entity_id' => [
|
||||
[
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/entity_test/1?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/entity_test/bar',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
['value' => $commented_entity->uuid()]
|
||||
],
|
||||
],
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/comment/comment/uid' => [
|
||||
[
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
['value' => $author->uuid()]
|
||||
],
|
||||
'lang' => 'en',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/comment/comment',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
// The 'url.site' cache context is added for '_links' in the response.
|
||||
return Cache::mergeTags(parent::getExpectedCacheContexts(), ['url.site']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\ConfigTest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\ConfigTest\ConfigTestResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class ConfigTestHalJsonAnonTest extends ConfigTestResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\ConfigTest;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\ConfigTest\ConfigTestResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class ConfigTestHalJsonBasicAuthTest extends ConfigTestResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\ConfigTest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\ConfigTest\ConfigTestResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class ConfigTestHalJsonCookieTest extends ConfigTestResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\EntityTest;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityTest\EntityTestResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class EntityTestHalJsonAnonTest extends EntityTestResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
|
||||
$author = User::load(0);
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/entity_test/1?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/entity_test/entity_test',
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/entity_test/entity_test/user_id' => [
|
||||
[
|
||||
'href' => $this->baseUrl . '/user/0?_format=hal_json',
|
||||
'lang' => 'en',
|
||||
],
|
||||
],
|
||||
],
|
||||
'_embedded' => [
|
||||
$this->baseUrl . '/rest/relation/entity_test/entity_test/user_id' => [
|
||||
[
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/user/0?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
['value' => $author->uuid()]
|
||||
],
|
||||
'lang' => 'en',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/entity_test/entity_test',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
// The 'url.site' cache context is added for '_links' in the response.
|
||||
return Cache::mergeTags(parent::getExpectedCacheContexts(), ['url.site']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\EntityTest;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class EntityTestHalJsonBasicAuthTest extends EntityTestHalJsonAnonTest {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\EntityTest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class EntityTestHalJsonCookieTest extends EntityTestHalJsonAnonTest {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource;
|
||||
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Url;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
/**
|
||||
* Trait for EntityResourceTestBase subclasses testing formats using HAL.
|
||||
*/
|
||||
trait HalEntityNormalizationTrait {
|
||||
|
||||
/**
|
||||
* Applies the HAL entity field normalization to an entity normalization.
|
||||
*
|
||||
* The HAL normalization:
|
||||
* - adds a 'lang' attribute to every translatable field
|
||||
* - omits reference fields, since references are stored in _links & _embedded
|
||||
* - omits empty fields (fields without value)
|
||||
*
|
||||
* @param array $normalization
|
||||
* An entity normalization.
|
||||
*
|
||||
* @return array
|
||||
* The updated entity normalization.
|
||||
*/
|
||||
protected function applyHalFieldNormalization(array $normalization) {
|
||||
if (!$this->entity instanceof FieldableEntityInterface) {
|
||||
throw new \LogicException('This trait should only be used for fieldable entity types.');
|
||||
}
|
||||
|
||||
// In the HAL normalization, all translatable fields get a 'lang' attribute.
|
||||
$translatable_non_reference_fields = array_keys(array_filter($this->entity->getTranslatableFields(), function (FieldItemListInterface $field) {
|
||||
return !$field instanceof EntityReferenceFieldItemListInterface;
|
||||
}));
|
||||
foreach ($translatable_non_reference_fields as $field_name) {
|
||||
if (isset($normalization[$field_name])) {
|
||||
$normalization[$field_name][0]['lang'] = 'en';
|
||||
}
|
||||
}
|
||||
|
||||
// In the HAL normalization, reference fields are omitted, except for the
|
||||
// bundle field.
|
||||
$bundle_key = $this->entity->getEntityType()->getKey('bundle');
|
||||
$reference_fields = array_keys(array_filter($this->entity->getFields(), function (FieldItemListInterface $field) use ($bundle_key) {
|
||||
return $field instanceof EntityReferenceFieldItemListInterface && $field->getName() !== $bundle_key;
|
||||
}));
|
||||
foreach ($reference_fields as $field_name) {
|
||||
unset($normalization[$field_name]);
|
||||
}
|
||||
|
||||
// In the HAL normalization, the bundle field omits the 'target_type' and
|
||||
// 'target_uuid' properties, because it's encoded in the '_links' section.
|
||||
if ($bundle_key) {
|
||||
unset($normalization[$bundle_key][0]['target_type']);
|
||||
unset($normalization[$bundle_key][0]['target_uuid']);
|
||||
}
|
||||
|
||||
// In the HAL normalization, empty fields are omitted.
|
||||
$empty_fields = array_keys(array_filter($this->entity->getFields(), function (FieldItemListInterface $field) {
|
||||
return $field->isEmpty();
|
||||
}));
|
||||
foreach ($empty_fields as $field_name) {
|
||||
unset($normalization[$field_name]);
|
||||
}
|
||||
|
||||
return $normalization;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function removeFieldsFromNormalization(array $normalization, $field_names) {
|
||||
$normalization = parent::removeFieldsFromNormalization($normalization, $field_names);
|
||||
foreach ($field_names as $field_name) {
|
||||
$relation_url = Url::fromUri('base:rest/relation/' . static::$entityTypeId . '/' . $this->entity->bundle() . '/' . $field_name)
|
||||
->setAbsolute(TRUE)
|
||||
->toString();
|
||||
$normalization['_links'] = array_diff_key($normalization['_links'], [$relation_url => TRUE]);
|
||||
if (isset($normalization['_embedded'])) {
|
||||
$normalization['_embedded'] = array_diff_key($normalization['_embedded'], [$relation_url => TRUE]);
|
||||
}
|
||||
}
|
||||
|
||||
return array_diff_key($normalization, array_flip($field_names));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertNormalizationEdgeCases($method, Url $url, array $request_options) {
|
||||
// \Drupal\serialization\Normalizer\EntityNormalizer::denormalize(): entity
|
||||
// types with bundles MUST send their bundle field to be denormalizable.
|
||||
if ($this->entity->getEntityType()->hasKey('bundle')) {
|
||||
$normalization = $this->getNormalizedPostEntity();
|
||||
|
||||
// @todo Uncomment this in https://www.drupal.org/node/2824827.
|
||||
// @codingStandardsIgnoreStart
|
||||
/*
|
||||
$normalization['_links']['type'] = Url::fromUri('base:rest/type/' . static::$entityTypeId . '/bad_bundle_name');
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
|
||||
|
||||
// DX: 400 when incorrect entity type bundle is specified.
|
||||
$response = $this->request($method, $url, $request_options);
|
||||
// @todo Uncomment, remove next 3 in https://www.drupal.org/node/2813853.
|
||||
// $this->assertResourceErrorResponse(400, 'The type link relation must be specified.', $response);
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
$this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
|
||||
$this->assertSame($this->serializer->encode(['error' => 'The type link relation must be specified.'], static::$format), (string) $response->getBody());
|
||||
*/
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
unset($normalization['_links']['type']);
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
|
||||
|
||||
|
||||
// DX: 400 when no entity type bundle is specified.
|
||||
$response = $this->request($method, $url, $request_options);
|
||||
// @todo Uncomment, remove next 3 in https://www.drupal.org/node/2813853.
|
||||
// $this->assertResourceErrorResponse(400, 'The type link relation must be specified.', $response);
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
$this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
|
||||
$this->assertSame($this->serializer->encode(['error' => 'The type link relation must be specified.'], static::$format), (string) $response->getBody());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Node;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class NodeHalJsonAnonTest extends NodeResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'created',
|
||||
'changed',
|
||||
'promote',
|
||||
'sticky',
|
||||
'revision_timestamp',
|
||||
'revision_uid',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
|
||||
$author = User::load($this->entity->getOwnerId());
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/node/1?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/node/camelids',
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/node/camelids/uid' => [
|
||||
[
|
||||
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
|
||||
'lang' => 'en',
|
||||
],
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [
|
||||
[
|
||||
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
|
||||
],
|
||||
],
|
||||
],
|
||||
'_embedded' => [
|
||||
$this->baseUrl . '/rest/relation/node/camelids/uid' => [
|
||||
[
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
['value' => $author->uuid()]
|
||||
],
|
||||
'lang' => 'en',
|
||||
],
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [
|
||||
[
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
['value' => $author->uuid()]
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/node/camelids',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
// The 'url.site' cache context is added for '_links' in the response.
|
||||
return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['url.site']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Node;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class NodeHalJsonBasicAuthTest extends NodeHalJsonAnonTest {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Node;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class NodeHalJsonCookieTest extends NodeHalJsonAnonTest {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Role;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Role\RoleResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class RoleHalJsonAnonTest extends RoleResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Role;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Role\RoleResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class RoleHalJsonBasicAuthTest extends RoleResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Role;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Role\RoleResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class RoleHalJsonCookieTest extends RoleResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Term;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class TermHalJsonAnonTest extends TermResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/taxonomy/term/1?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
// The 'url.site' cache context is added for '_links' in the response.
|
||||
return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['url.site']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Term;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class TermHalJsonBasicAuthTest extends TermHalJsonAnonTest {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Term;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class TermHalJsonCookieTest extends TermHalJsonAnonTest {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\User;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\User\UserResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class UserHalJsonAnonTest extends UserResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/user/3?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
// The 'url.site' cache context is added for '_links' in the response.
|
||||
return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['url.site']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\User;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class UserHalJsonBasicAuthTest extends UserHalJsonAnonTest {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\User;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class UserHalJsonCookieTest extends UserHalJsonAnonTest {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Vocabulary;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Vocabulary\VocabularyResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class VocabularyHalJsonAnonTest extends VocabularyResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* @todo Remove this override in https://www.drupal.org/node/2805281.
|
||||
*/
|
||||
public function testGet() {
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Vocabulary;
|
||||
|
||||
use Drupal\Tests\hal\Functional\HalJsonBasicAuthWorkaroundFor2805281Trait;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Vocabulary\VocabularyResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class VocabularyHalJsonBasicAuthTest extends VocabularyResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2805281: remove this trait usage.
|
||||
use HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
HalJsonBasicAuthWorkaroundFor2805281Trait::assertResponseWhenMissingAuthentication insteadof BasicAuthResourceTestTrait;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\Vocabulary;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\Vocabulary\VocabularyResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class VocabularyHalJsonCookieTest extends VocabularyResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $expectedErrorMimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
trait HalJsonBasicAuthWorkaroundFor2805281Trait {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Note how the response claims it contains a application/hal+json body, but
|
||||
* in reality it contains a text/plain body! Also, the correct error MIME type
|
||||
* is application/json.
|
||||
*
|
||||
* @todo Fix in https://www.drupal.org/node/2805281: remove this trait.
|
||||
*/
|
||||
protected function assertResponseWhenMissingAuthentication(ResponseInterface $response) {
|
||||
$this->assertSame(401, $response->getStatusCode());
|
||||
// @todo this works fine locally, but on testbot it comes back with
|
||||
// 'text/plain; charset=UTF-8'. WTF.
|
||||
// $this->assertSame(['application/hal+json'], $response->getHeader('Content-Type'));
|
||||
$this->assertSame('No authentication credentials provided.', (string) $response->getBody());
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ use Drupal\field\Entity\FieldConfig;
|
|||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Tests that entities can be denormalized from HAL.
|
||||
* Tests HAL denormalization edge cases for EntityResource.
|
||||
*
|
||||
* @group hal
|
||||
*/
|
||||
|
@ -110,98 +110,4 @@ class DenormalizeTest extends NormalizerTestBase {
|
|||
$this->assertEqual($entity->field_test_text->count(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that non-reference fields can be denormalized.
|
||||
*/
|
||||
public function testBasicFieldDenormalization() {
|
||||
$data = array(
|
||||
'_links' => array(
|
||||
'type' => array(
|
||||
'href' => Url::fromUri('base:rest/type/entity_test/entity_test', array('absolute' => TRUE))->toString(),
|
||||
),
|
||||
),
|
||||
'uuid' => array(
|
||||
array(
|
||||
'value' => 'e5c9fb96-3acf-4a8d-9417-23de1b6c3311',
|
||||
),
|
||||
),
|
||||
'field_test_text' => array(
|
||||
array(
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => 'full_html',
|
||||
),
|
||||
),
|
||||
'field_test_translatable_text' => array(
|
||||
array(
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => 'full_html',
|
||||
),
|
||||
array(
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => 'filtered_html',
|
||||
),
|
||||
array(
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => 'filtered_html',
|
||||
'lang' => 'de',
|
||||
),
|
||||
array(
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => 'full_html',
|
||||
'lang' => 'de',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$expected_value_default = array(
|
||||
array (
|
||||
'value' => $data['field_test_translatable_text'][0]['value'],
|
||||
'format' => 'full_html',
|
||||
),
|
||||
array (
|
||||
'value' => $data['field_test_translatable_text'][1]['value'],
|
||||
'format' => 'filtered_html',
|
||||
),
|
||||
);
|
||||
$expected_value_de = array(
|
||||
array (
|
||||
'value' => $data['field_test_translatable_text'][2]['value'],
|
||||
'format' => 'filtered_html',
|
||||
),
|
||||
array (
|
||||
'value' => $data['field_test_translatable_text'][3]['value'],
|
||||
'format' => 'full_html',
|
||||
),
|
||||
);
|
||||
$denormalized = $this->serializer->denormalize($data, $this->entityClass, $this->format);
|
||||
$this->assertEqual($data['uuid'], $denormalized->get('uuid')->getValue(), 'A preset value (e.g. UUID) is overridden by incoming data.');
|
||||
$this->assertEqual($data['field_test_text'], $denormalized->get('field_test_text')->getValue(), 'A basic text field is denormalized.');
|
||||
$this->assertEqual($expected_value_default, $denormalized->get('field_test_translatable_text')->getValue(), 'Values in the default language are properly handled for a translatable field.');
|
||||
$this->assertEqual($expected_value_de, $denormalized->getTranslation('de')->get('field_test_translatable_text')->getValue(), 'Values in a translation language are properly handled for a translatable field.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the denormalized entity is correct in the PATCH context.
|
||||
*/
|
||||
public function testPatchDenormalization() {
|
||||
$data = array(
|
||||
'_links' => array(
|
||||
'type' => array(
|
||||
'href' => Url::fromUri('base:rest/type/entity_test/entity_test', array('absolute' => TRUE))->toString(),
|
||||
),
|
||||
),
|
||||
'field_test_text' => array(
|
||||
array(
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => 'full_html',
|
||||
),
|
||||
),
|
||||
);
|
||||
$denormalized = $this->serializer->denormalize($data, $this->entityClass, $this->format, array('request_method' => 'patch'));
|
||||
// Check that the one field got populated as expected.
|
||||
$this->assertEqual($data['field_test_text'], $denormalized->get('field_test_text')->getValue());
|
||||
// Check the custom property that contains the list of fields to merge.
|
||||
$this->assertEqual($denormalized->_restSubmittedFields, ['field_test_text']);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,206 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Kernel;
|
||||
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
|
||||
/**
|
||||
* Tests that nodes and terms are correctly normalized and denormalized.
|
||||
*
|
||||
* @group hal
|
||||
*/
|
||||
class EntityNormalizeTest extends NormalizerTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'taxonomy', 'comment');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
$this->installSchema('system', array('sequences'));
|
||||
$this->installSchema('comment', array('comment_entity_statistics'));
|
||||
$this->installEntitySchema('taxonomy_term');
|
||||
$this->installConfig(['node', 'comment']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the normalization of nodes.
|
||||
*/
|
||||
public function testNode() {
|
||||
$node_type = NodeType::create(['type' => 'example_type']);
|
||||
$node_type->save();
|
||||
|
||||
$user = User::create(['name' => $this->randomMachineName()]);
|
||||
$user->save();
|
||||
|
||||
// Add comment type.
|
||||
$this->container->get('entity.manager')->getStorage('comment_type')->create(array(
|
||||
'id' => 'comment',
|
||||
'label' => 'comment',
|
||||
'target_entity_type_id' => 'node',
|
||||
))->save();
|
||||
|
||||
$this->addDefaultCommentField('node', 'example_type');
|
||||
|
||||
$node = Node::create([
|
||||
'title' => $this->randomMachineName(),
|
||||
'uid' => $user->id(),
|
||||
'type' => $node_type->id(),
|
||||
'status' => NODE_PUBLISHED,
|
||||
'promote' => 1,
|
||||
'sticky' => 0,
|
||||
'body' => [
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => $this->randomMachineName()
|
||||
],
|
||||
'revision_log' => $this->randomString(),
|
||||
]);
|
||||
$node->save();
|
||||
|
||||
$original_values = $node->toArray();
|
||||
|
||||
$normalized = $this->serializer->normalize($node, $this->format);
|
||||
|
||||
/** @var \Drupal\node\NodeInterface $denormalized_node */
|
||||
$denormalized_node = $this->serializer->denormalize($normalized, 'Drupal\node\Entity\Node', $this->format);
|
||||
|
||||
$this->assertEqual($original_values, $denormalized_node->toArray(), 'Node values are restored after normalizing and denormalizing.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the normalization of terms.
|
||||
*/
|
||||
public function testTerm() {
|
||||
$vocabulary = Vocabulary::create(['vid' => 'example_vocabulary']);
|
||||
$vocabulary->save();
|
||||
|
||||
$account = User::create(['name' => $this->randomMachineName()]);
|
||||
$account->save();
|
||||
|
||||
// @todo Until https://www.drupal.org/node/2327935 is fixed, if no parent is
|
||||
// set, the test fails because target_id => 0 is reserialized to NULL.
|
||||
$term_parent = Term::create([
|
||||
'name' => $this->randomMachineName(),
|
||||
'vid' => $vocabulary->id(),
|
||||
]);
|
||||
$term_parent->save();
|
||||
$term = Term::create([
|
||||
'name' => $this->randomMachineName(),
|
||||
'vid' => $vocabulary->id(),
|
||||
'description' => array(
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => $this->randomMachineName(),
|
||||
),
|
||||
'parent' => $term_parent->id(),
|
||||
]);
|
||||
$term->save();
|
||||
|
||||
$original_values = $term->toArray();
|
||||
|
||||
$normalized = $this->serializer->normalize($term, $this->format, ['account' => $account]);
|
||||
|
||||
/** @var \Drupal\taxonomy\TermInterface $denormalized_term */
|
||||
$denormalized_term = $this->serializer->denormalize($normalized, 'Drupal\taxonomy\Entity\Term', $this->format, ['account' => $account]);
|
||||
|
||||
$this->assertEqual($original_values, $denormalized_term->toArray(), 'Term values are restored after normalizing and denormalizing.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the normalization of comments.
|
||||
*/
|
||||
public function testComment() {
|
||||
$node_type = NodeType::create(['type' => 'example_type']);
|
||||
$node_type->save();
|
||||
|
||||
$account = User::create(['name' => $this->randomMachineName()]);
|
||||
$account->save();
|
||||
|
||||
// Add comment type.
|
||||
$this->container->get('entity.manager')->getStorage('comment_type')->create(array(
|
||||
'id' => 'comment',
|
||||
'label' => 'comment',
|
||||
'target_entity_type_id' => 'node',
|
||||
))->save();
|
||||
|
||||
$this->addDefaultCommentField('node', 'example_type');
|
||||
|
||||
$node = Node::create([
|
||||
'title' => $this->randomMachineName(),
|
||||
'uid' => $account->id(),
|
||||
'type' => $node_type->id(),
|
||||
'status' => NODE_PUBLISHED,
|
||||
'promote' => 1,
|
||||
'sticky' => 0,
|
||||
'body' => [[
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => $this->randomMachineName()
|
||||
]],
|
||||
]);
|
||||
$node->save();
|
||||
|
||||
$parent_comment = Comment::create(array(
|
||||
'uid' => $account->id(),
|
||||
'subject' => $this->randomMachineName(),
|
||||
'comment_body' => [
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => NULL,
|
||||
],
|
||||
'entity_id' => $node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment',
|
||||
));
|
||||
$parent_comment->save();
|
||||
|
||||
$comment = Comment::create(array(
|
||||
'uid' => $account->id(),
|
||||
'subject' => $this->randomMachineName(),
|
||||
'comment_body' => [
|
||||
'value' => $this->randomMachineName(),
|
||||
'format' => NULL,
|
||||
],
|
||||
'entity_id' => $node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment',
|
||||
'pid' => $parent_comment->id(),
|
||||
'mail' => 'dries@drupal.org',
|
||||
'homepage' => 'http://buytaert.net',
|
||||
));
|
||||
$comment->save();
|
||||
|
||||
$original_values = $comment->toArray();
|
||||
// Hostname will always be denied view access.
|
||||
// No value will exist for name as this is only for anonymous users.
|
||||
unset($original_values['hostname'], $original_values['name']);
|
||||
|
||||
$normalized = $this->serializer->normalize($comment, $this->format, ['account' => $account]);
|
||||
|
||||
// Assert that the hostname field does not appear at all in the normalized
|
||||
// data.
|
||||
$this->assertFalse(array_key_exists('hostname', $normalized), 'Hostname was not found in normalized comment data.');
|
||||
|
||||
/** @var \Drupal\comment\CommentInterface $denormalized_comment */
|
||||
$denormalized_comment = $this->serializer->denormalize($normalized, 'Drupal\comment\Entity\Comment', $this->format, ['account' => $account]);
|
||||
|
||||
// Before comparing, unset values that are expected to differ.
|
||||
$denormalized_comment_values = $denormalized_comment->toArray();
|
||||
unset($denormalized_comment_values['hostname'], $denormalized_comment_values['name']);
|
||||
$this->assertEqual($original_values, $denormalized_comment_values, 'The expected comment values are restored after normalizing and denormalizing.');
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ use Drupal\Core\Url;
|
|||
use Drupal\entity_test\Entity\EntityTest;
|
||||
|
||||
/**
|
||||
* Tests that entities can be normalized in HAL.
|
||||
* Tests HAL normalization edge cases for EntityResource.
|
||||
*
|
||||
* @group hal
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
id: d6_language_negotiation_settings
|
||||
label: Language negotiation settings
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- language_negotiation
|
||||
process:
|
||||
session/parameter:
|
||||
plugin: default_value
|
||||
default_value: 'language'
|
||||
selected_langcode:
|
||||
plugin: default_value
|
||||
default_value: 'site_default'
|
||||
url/source:
|
||||
plugin: static_map
|
||||
source: language_negotiation
|
||||
default_value: path_prefix
|
||||
map:
|
||||
# LANGUAGE_NEGOTIATION_NONE = 0
|
||||
# LANGUAGE_NEGOTIATION_PATH_DEFAULT = 1
|
||||
# LANGUAGE_NEGOTIATION_PATH = 2
|
||||
# LANGUAGE_NEGOTIATION_DOMAIN = 3
|
||||
0: path_prefix
|
||||
1: path_prefix
|
||||
2: path_prefix
|
||||
3: domain
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: language.negotiation
|
||||
migration_dependencies:
|
||||
required:
|
||||
- language
|
|
@ -0,0 +1,52 @@
|
|||
id: d6_language_types
|
||||
label: Language types
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- language_negotiation
|
||||
process:
|
||||
all:
|
||||
plugin: default_value
|
||||
default_value:
|
||||
- 'language_interface'
|
||||
- 'language_content'
|
||||
- 'language_url'
|
||||
configurable:
|
||||
plugin: default_value
|
||||
default_value:
|
||||
- 'language_interface'
|
||||
negotiation/language_content/enabled:
|
||||
plugin: default_value
|
||||
default_value:
|
||||
'language-interface': 0
|
||||
negotiation/language_url/enabled:
|
||||
plugin: default_value
|
||||
default_value:
|
||||
'language-url': 0
|
||||
'language-url-fallback': 1
|
||||
negotiation/language_interface/enabled:
|
||||
plugin: static_map
|
||||
source: language_negotiation
|
||||
map:
|
||||
# LANGUAGE_NEGOTIATION_NONE = 0
|
||||
# LANGUAGE_NEGOTIATION_PATH_DEFAULT = 1
|
||||
# LANGUAGE_NEGOTIATION_PATH = 2
|
||||
# LANGUAGE_NEGOTIATION_DOMAIN = 3
|
||||
0:
|
||||
'language-selected': 0
|
||||
1:
|
||||
'language-url': 0
|
||||
'language-selected': 1
|
||||
2:
|
||||
'language-url': 0
|
||||
'language-user': 1
|
||||
'language-browser': 2
|
||||
'language-selected': 3
|
||||
3:
|
||||
'language-url': 0
|
||||
'language-selected': 1
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: language.types
|
|
@ -8,8 +8,25 @@ source:
|
|||
- locale_language_negotiation_session_param
|
||||
- locale_language_negotiation_url_part
|
||||
process:
|
||||
'session/parameter': locale_language_negotiation_session_param
|
||||
'url/source': locale_language_negotiation_url_part
|
||||
session/parameter:
|
||||
plugin: default_value
|
||||
source: locale_language_negotiation_session_param
|
||||
default_value: 'language'
|
||||
selected_langcode:
|
||||
plugin: default_value
|
||||
default_value: 'site_default'
|
||||
url/source:
|
||||
plugin: static_map
|
||||
source: locale_language_negotiation_url_part
|
||||
default_value: path_prefix
|
||||
map:
|
||||
# LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX = 0
|
||||
# LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN = 1
|
||||
0: path_prefix
|
||||
1: domain
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: language.negotiation
|
||||
migration_dependencies:
|
||||
required:
|
||||
- language
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue