Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
|
@ -0,0 +1,3 @@
|
|||
name: Accept header based routing test
|
||||
core: 8.x
|
||||
type: module
|
|
@ -0,0 +1,5 @@
|
|||
services:
|
||||
accept_header_matcher:
|
||||
class: Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher
|
||||
tags:
|
||||
- { name: route_filter }
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\accept_header_routing_test\AcceptHeaderMiddleware.
|
||||
*/
|
||||
|
||||
namespace Drupal\accept_header_routing_test;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Example implementation of accept header based content negotation.
|
||||
*/
|
||||
class AcceptHeaderMiddleware implements HttpKernelInterface {
|
||||
|
||||
/**
|
||||
* Constructs a new AcceptHeaderMiddleware instance.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\HttpKernelInterface $app
|
||||
* The app.
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $app) {
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
|
||||
$mapping = [
|
||||
'application/json' => 'json',
|
||||
'application/hal+json' => 'hal_json',
|
||||
'application/xml' => 'xml',
|
||||
'text/html' => 'html',
|
||||
];
|
||||
|
||||
$accept = $request->headers->get('Accept') ?: ['text/html'];
|
||||
if (isset($mapping[$accept[0]])) {
|
||||
$request->setRequestFormat($mapping[$accept[0]]);
|
||||
}
|
||||
|
||||
return $this->app->handle($request, $type, $catch);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\accept_header_routing_test\AcceptHeaderRoutingTestServiceProvider.
|
||||
*/
|
||||
|
||||
namespace Drupal\accept_header_routing_test;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
|
||||
|
||||
/**
|
||||
* Service provider for the accept_header_routing_test module.
|
||||
*/
|
||||
class AcceptHeaderRoutingTestServiceProvider implements ServiceModifierInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
// Remove the basic content negotation middleware and replace it with a
|
||||
// basic header based one.
|
||||
$container->register('http_middleware.negotiation', 'Drupal\accept_header_routing_test\AcceptHeaderMiddleware')
|
||||
->addTag('http_middleware', ['priority' => 400]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher.
|
||||
*/
|
||||
|
||||
namespace Drupal\accept_header_routing_test\Routing;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Routing\RouteFilterInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Filters routes based on the media type specified in the HTTP Accept headers.
|
||||
*/
|
||||
class AcceptHeaderMatcher implements RouteFilterInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function filter(RouteCollection $collection, Request $request) {
|
||||
// Generates a list of Symfony formats matching the acceptable MIME types.
|
||||
// @todo replace by proper content negotiation library.
|
||||
$acceptable_mime_types = $request->getAcceptableContentTypes();
|
||||
$acceptable_formats = array_filter(array_map(array($request, 'getFormat'), $acceptable_mime_types));
|
||||
$primary_format = $request->getRequestFormat();
|
||||
|
||||
foreach ($collection as $name => $route) {
|
||||
// _format could be a |-delimited list of supported formats.
|
||||
$supported_formats = array_filter(explode('|', $route->getRequirement('_format')));
|
||||
|
||||
if (empty($supported_formats)) {
|
||||
// No format restriction on the route, so it always matches. Move it to
|
||||
// the end of the collection by re-adding it.
|
||||
$collection->add($name, $route);
|
||||
}
|
||||
elseif (in_array($primary_format, $supported_formats)) {
|
||||
// Perfect match, which will get a higher priority by leaving the route
|
||||
// on top of the list.
|
||||
}
|
||||
// The route partially matches if it doesn't care about format, if it
|
||||
// explicitly allows any format, or if one of its allowed formats is
|
||||
// in the request's list of acceptable formats.
|
||||
elseif (in_array('*/*', $acceptable_mime_types) || array_intersect($acceptable_formats, $supported_formats)) {
|
||||
// Move it to the end of the list.
|
||||
$collection->add($name, $route);
|
||||
}
|
||||
else {
|
||||
// Remove the route if it does not match at all.
|
||||
$collection->remove($name);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($collection)) {
|
||||
return $collection;
|
||||
}
|
||||
|
||||
// We do not throw a
|
||||
// \Symfony\Component\Routing\Exception\ResourceNotFoundException here
|
||||
// because we don't want to return a 404 status code, but rather a 406.
|
||||
throw new NotAcceptableHttpException(SafeMarkup::format('No route found for the specified formats @formats.', array('@formats' => implode(' ', $acceptable_mime_types))));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies(Route $route) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\accept_header_routing_teste\Unit\Routing\AcceptHeaderMatcherTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\accept_header_routing_teste\Unit\Routing;
|
||||
|
||||
use Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher;
|
||||
use Drupal\Tests\Core\Routing\RoutingFixtures;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Confirm that the mime types partial matcher is functioning properly.
|
||||
*
|
||||
* @group Routing
|
||||
*/
|
||||
class AcceptHeaderMatcherTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* A collection of shared fixture data for tests.
|
||||
*
|
||||
* @var \Drupal\Tests\Core\Routing\RoutingFixtures
|
||||
*/
|
||||
protected $fixtures;
|
||||
|
||||
/**
|
||||
* The matcher object that is going to be tested.
|
||||
*
|
||||
* @var \Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher
|
||||
*/
|
||||
protected $matcher;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->fixtures = new RoutingFixtures();
|
||||
$this->matcher = new AcceptHeaderMatcher();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for the Accept header filtering test.
|
||||
*
|
||||
* @see Drupal\Tests\Core\Routing\AcceptHeaderMatcherTest::testAcceptFiltering()
|
||||
*/
|
||||
public function acceptFilterProvider() {
|
||||
return [
|
||||
// Check that JSON routes get filtered and prioritized correctly.
|
||||
['application/json, text/xml;q=0.9', 'json', 'route_c', 'route_e'],
|
||||
// Tests a JSON request with alternative JSON MIME type Accept header.
|
||||
['application/x-json, text/xml;q=0.9', 'json', 'route_c', 'route_e'],
|
||||
// Tests a standard HTML request.
|
||||
['text/html, text/xml;q=0.9', 'html', 'route_e', 'route_c'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that requests using Accept headers get filtered correctly.
|
||||
*
|
||||
* @param string $accept_header
|
||||
* The HTTP Accept header value of the request.
|
||||
* @param string $format
|
||||
* The request format.
|
||||
* @param string $included_route
|
||||
* The route name that should survive the filter and be ranked first.
|
||||
* @param string $excluded_route
|
||||
* The route name that should be filtered out during matching.
|
||||
*
|
||||
* @dataProvider acceptFilterProvider
|
||||
*/
|
||||
public function testAcceptFiltering($accept_header, $format, $included_route, $excluded_route) {
|
||||
$collection = $this->fixtures->sampleRouteCollection();
|
||||
|
||||
$request = Request::create('path/two', 'GET');
|
||||
$request->headers->set('Accept', $accept_header);
|
||||
$request->setRequestFormat($format);
|
||||
$routes = $this->matcher->filter($collection, $request);
|
||||
$this->assertEquals(count($routes), 4, 'The correct number of routes was found.');
|
||||
$this->assertNotNull($routes->get($included_route), "Route $included_route was found when matching $accept_header.");
|
||||
$this->assertNull($routes->get($excluded_route), "Route $excluded_route was not found when matching $accept_header.");
|
||||
foreach ($routes as $name => $route) {
|
||||
$this->assertEquals($name, $included_route, "Route $included_route is the first one in the collection when matching $accept_header.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms that the AcceptHeaderMatcher throws an exception for no-route.
|
||||
*
|
||||
* @expectedException \Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException
|
||||
* @expectedExceptionMessage No route found for the specified formats application/json text/xml.
|
||||
*/
|
||||
public function testNoRouteFound() {
|
||||
// Remove the sample routes that would match any method.
|
||||
$routes = $this->fixtures->sampleRouteCollection();
|
||||
$routes->remove('route_a');
|
||||
$routes->remove('route_b');
|
||||
$routes->remove('route_c');
|
||||
$routes->remove('route_d');
|
||||
|
||||
$request = Request::create('path/two', 'GET');
|
||||
$request->headers->set('Accept', 'application/json, text/xml;q=0.9');
|
||||
$request->setRequestFormat('json');
|
||||
$this->matcher->filter($routes, $request);
|
||||
$this->matcher->filter($routes, $request);
|
||||
$this->fail('No exception was thrown.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Action test'
|
||||
type: module
|
||||
description: 'Support module for action testing.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\action_test\Plugin\Action\NoType.
|
||||
*/
|
||||
|
||||
namespace Drupal\action_test\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Provides an operation with no type specified.
|
||||
*
|
||||
* @Action(
|
||||
* id = "action_test_no_type",
|
||||
* label = @Translation("An operation with no type specified")
|
||||
* )
|
||||
*/
|
||||
class NoType extends ActionBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
$result = AccessResult::allowed();
|
||||
return $return_as_object ? $result : $result->isAllowed();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\action_test\Plugin\Action\SaveEntity.
|
||||
*/
|
||||
|
||||
namespace Drupal\action_test\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Provides an operation to save user entities.
|
||||
*
|
||||
* @Action(
|
||||
* id = "action_test_save_entity",
|
||||
* label = @Translation("Saves entities"),
|
||||
* type = "user"
|
||||
* )
|
||||
*/
|
||||
class SaveEntity extends ActionBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$entity->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\Core\Entity\EntityInterface $object */
|
||||
return $object->access('update', $account, $return_as_object);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'AJAX form test mock module'
|
||||
type: module
|
||||
description: 'Test for AJAX form calls.'
|
||||
core: 8.x
|
||||
package: Testing
|
||||
version: VERSION
|
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Simpletest mock module for Ajax forms testing.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Ajax;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'after'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_after_callback($form, FormStateInterface $form_state) {
|
||||
$selector = '#after_div';
|
||||
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\AfterCommand($selector, "This will be placed after"));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'alert'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_alert_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\AlertCommand('Alert'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'append'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_append_callback($form, FormStateInterface $form_state) {
|
||||
$selector = '#append_div';
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\AppendCommand($selector, "Appended text"));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'before'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_before_callback($form, FormStateInterface $form_state) {
|
||||
$selector = '#before_div';
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\BeforeCommand($selector, "Before text"));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'changed'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_changed_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\ChangedCommand('#changed_div'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'changed' with asterisk marking inner div.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_changed_asterisk_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\ChangedCommand('#changed_div', '#changed_div_mark_this'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'css'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_css_callback($form, FormStateInterface $form_state) {
|
||||
$selector = '#css_div';
|
||||
$color = 'blue';
|
||||
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\CssCommand($selector, array('background-color' => $color)));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'data'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_data_callback($form, FormStateInterface $form_state) {
|
||||
$selector = '#data_div';
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\DataCommand($selector, 'testkey', 'testvalue'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'invoke'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_invoke_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\InvokeCommand('#invoke_div', 'addClass', array('error')));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'html'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_html_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\HtmlCommand('#html_div', 'replacement text'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'insert'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_insert_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\InsertCommand('#insert_div', 'insert replacement text'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'prepend'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_prepend_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\PrependCommand('#prepend_div', "prepended text"));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'remove'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_remove_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\RemoveCommand('#remove_text'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'restripe'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_restripe_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\RestripeCommand('#restripe_table'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects 'settings'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_settings_callback($form, FormStateInterface $form_state) {
|
||||
$setting['ajax_forms_test']['foo'] = 42;
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\SettingsCommand($setting));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback for 'add_css'.
|
||||
*/
|
||||
function ajax_forms_test_advanced_commands_add_css_callback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new Ajax\AddCssCommand('my/file.css'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects the 'drivertext' element of the validation form.
|
||||
*/
|
||||
function ajax_forms_test_validation_form_callback($form, FormStateInterface $form_state) {
|
||||
drupal_set_message("ajax_forms_test_validation_form_callback invoked");
|
||||
drupal_set_message(t("Callback: drivertext=%drivertext, spare_required_field=%spare_required_field", array('%drivertext' => $form_state->getValue('drivertext'), '%spare_required_field' => $form_state->getValue('spare_required_field'))));
|
||||
return ['#markup' => '<div id="message_area">ajax_forms_test_validation_form_callback at ' . date('c') . '</div>'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax form callback: Selects the 'drivernumber' element of the validation form.
|
||||
*/
|
||||
function ajax_forms_test_validation_number_form_callback($form, FormStateInterface $form_state) {
|
||||
drupal_set_message("ajax_forms_test_validation_number_form_callback invoked");
|
||||
drupal_set_message(t("Callback: drivernumber=%drivernumber, spare_required_field=%spare_required_field", array('%drivernumber' => $form_state->getValue('drivernumber'), '%spare_required_field' => $form_state->getValue('spare_required_field'))));
|
||||
return ['#markup' => '<div id="message_area_number">ajax_forms_test_validation_number_form_callback at ' . date('c') . '</div>'];
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX form callback: Selects for the ajax_forms_test_lazy_load_form() form.
|
||||
*/
|
||||
function ajax_forms_test_lazy_load_form_ajax($form, FormStateInterface $form_state) {
|
||||
$build = [
|
||||
'#markup' => 'new content',
|
||||
];
|
||||
|
||||
if ($form_state->getValue('add_files')) {
|
||||
$build['#attached']['library'][] = 'system/admin';
|
||||
$build['#attached']['library'][] = 'system/drupal.system';
|
||||
$build['#attached']['drupalSettings']['ajax_forms_test_lazy_load_form_submit'] = 'executed';
|
||||
}
|
||||
|
||||
return $build;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
ajax_forms_test.get_form:
|
||||
path: '/ajax_forms_test_get_form'
|
||||
defaults:
|
||||
_title: 'AJAX forms simple form test'
|
||||
_form: '\Drupal\ajax_forms_test\Form\AjaxFormsTestSimpleForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_forms_test.commands_form:
|
||||
path: '/ajax_forms_test_ajax_commands_form'
|
||||
defaults:
|
||||
_title: 'AJAX forms AJAX commands test'
|
||||
_form: '\Drupal\ajax_forms_test\Form\AjaxFormsTestCommandsForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_forms_test.validation_test:
|
||||
path: '/ajax_validation_test'
|
||||
defaults:
|
||||
_title: 'AJAX Validation Test'
|
||||
_form: '\Drupal\ajax_forms_test\Form\AjaxFormsTestValidationForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_forms_test.lazy_load_form:
|
||||
path: '/ajax_forms_test_lazy_load_form'
|
||||
defaults:
|
||||
_title: 'AJAX forms lazy load test'
|
||||
_form: '\Drupal\ajax_forms_test\Form\AjaxFormsTestLazyLoadForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_forms_test.cached_form:
|
||||
path: '/ajax_forms_test_cached_form'
|
||||
defaults:
|
||||
_title: 'AJAX forms cached form test'
|
||||
_form: '\Drupal\ajax_forms_test\Form\AjaxFormsTestCachedForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_forms_test\Callbacks.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_forms_test;
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\DataCommand;
|
||||
use Drupal\Core\Ajax\HtmlCommand;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Simple object for testing methods as Ajax callbacks.
|
||||
*/
|
||||
class Callbacks {
|
||||
|
||||
/**
|
||||
* Ajax callback triggered by select.
|
||||
*/
|
||||
function selectCallback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new HtmlCommand('#ajax_selected_color', $form_state->getValue('select')));
|
||||
$response->addCommand(new DataCommand('#ajax_selected_color', 'form_state_value_select', $form_state->getValue('select')));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback triggered by checkbox.
|
||||
*/
|
||||
function checkboxCallback($form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new HtmlCommand('#ajax_checkbox_value', (int) $form_state->getValue('checkbox')));
|
||||
$response->addCommand(new DataCommand('#ajax_checkbox_value', 'form_state_value_select', (int) $form_state->getValue('checkbox')));
|
||||
return $response;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_forms_test\Form\AjaxFormsTestCachedForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_forms_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Provides an AJAX form that will be cached.
|
||||
*/
|
||||
class AjaxFormsTestCachedForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_form_cache_test_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['test1'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Test 1'),
|
||||
'#options' => [
|
||||
'option1' => $this->t('Option 1'),
|
||||
'option2' => $this->t('Option 2'),
|
||||
],
|
||||
'#ajax' => [
|
||||
'url' => Url::fromRoute('system.ajax'),
|
||||
],
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_forms_test\Form\AjaxFormsTestCommandsForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_forms_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form constructor for the Ajax Command display form.
|
||||
*/
|
||||
class AjaxFormsTestCommandsForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}.
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_forms_test_ajax_commands_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}.
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form = array();
|
||||
|
||||
// Shows the 'after' command with a callback generating commands.
|
||||
$form['after_command_example'] = array(
|
||||
'#value' => $this->t("AJAX 'After': Click to put something after the div"),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_after_callback',
|
||||
),
|
||||
'#suffix' => '<div id="after_div">Something can be inserted after this</div>',
|
||||
);
|
||||
|
||||
// Shows the 'alert' command.
|
||||
$form['alert_command_example'] = array(
|
||||
'#value' => $this->t("AJAX 'Alert': Click to alert"),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_alert_callback',
|
||||
),
|
||||
);
|
||||
|
||||
// Shows the 'append' command.
|
||||
$form['append_command_example'] = array(
|
||||
'#value' => $this->t("AJAX 'Append': Click to append something"),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_append_callback',
|
||||
),
|
||||
'#suffix' => '<div id="append_div">Append inside this div</div>',
|
||||
);
|
||||
|
||||
|
||||
// Shows the 'before' command.
|
||||
$form['before_command_example'] = array(
|
||||
'#value' => $this->t("AJAX 'before': Click to put something before the div"),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_before_callback',
|
||||
),
|
||||
'#suffix' => '<div id="before_div">Insert something before this.</div>',
|
||||
);
|
||||
|
||||
// Shows the 'changed' command without asterisk.
|
||||
$form['changed_command_example'] = array(
|
||||
'#value' => $this->t("AJAX changed: Click to mark div changed."),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_changed_callback',
|
||||
),
|
||||
'#suffix' => '<div id="changed_div"> <div id="changed_div_mark_this">This div can be marked as changed or not.</div></div>',
|
||||
);
|
||||
// Shows the 'changed' command adding the asterisk.
|
||||
$form['changed_command_asterisk_example'] = array(
|
||||
'#value' => $this->t("AJAX changed: Click to mark div changed with asterisk."),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_changed_asterisk_callback',
|
||||
),
|
||||
);
|
||||
|
||||
// Shows the Ajax 'css' command.
|
||||
$form['css_command_example'] = array(
|
||||
'#value' => $this->t("Set the '#box' div to be blue."),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_css_callback',
|
||||
),
|
||||
'#suffix' => '<div id="css_div" style="height: 50px; width: 50px; border: 1px solid black"> box</div>',
|
||||
);
|
||||
|
||||
|
||||
// Shows the Ajax 'data' command. But there is no use of this information,
|
||||
// as this would require a javascript client to use the data.
|
||||
$form['data_command_example'] = array(
|
||||
'#value' => $this->t("AJAX data command: Issue command."),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_data_callback',
|
||||
),
|
||||
'#suffix' => '<div id="data_div">Data attached to this div.</div>',
|
||||
);
|
||||
|
||||
// Shows the Ajax 'invoke' command.
|
||||
$form['invoke_command_example'] = array(
|
||||
'#value' => $this->t("AJAX invoke command: Invoke addClass() method."),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_invoke_callback',
|
||||
),
|
||||
'#suffix' => '<div id="invoke_div">Original contents</div>',
|
||||
);
|
||||
|
||||
// Shows the Ajax 'html' command.
|
||||
$form['html_command_example'] = array(
|
||||
'#value' => $this->t("AJAX html: Replace the HTML in a selector."),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_html_callback',
|
||||
),
|
||||
'#suffix' => '<div id="html_div">Original contents</div>',
|
||||
);
|
||||
|
||||
// Shows the Ajax 'insert' command.
|
||||
$form['insert_command_example'] = array(
|
||||
'#value' => $this->t("AJAX insert: Let client insert based on #ajax['method']."),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_insert_callback',
|
||||
'method' => 'prepend',
|
||||
),
|
||||
'#suffix' => '<div id="insert_div">Original contents</div>',
|
||||
);
|
||||
|
||||
// Shows the Ajax 'prepend' command.
|
||||
$form['prepend_command_example'] = array(
|
||||
'#value' => $this->t("AJAX 'prepend': Click to prepend something"),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_prepend_callback',
|
||||
),
|
||||
'#suffix' => '<div id="prepend_div">Something will be prepended to this div. </div>',
|
||||
);
|
||||
|
||||
// Shows the Ajax 'remove' command.
|
||||
$form['remove_command_example'] = array(
|
||||
'#value' => $this->t("AJAX 'remove': Click to remove text"),
|
||||
'#type' => 'submit',
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_remove_callback',
|
||||
),
|
||||
'#suffix' => '<div id="remove_div"><div id="remove_text">text to be removed</div></div>',
|
||||
);
|
||||
|
||||
// Shows the Ajax 'restripe' command.
|
||||
$form['restripe_command_example'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t("AJAX 'restripe' command"),
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_restripe_callback',
|
||||
),
|
||||
'#suffix' => '<div id="restripe_div">
|
||||
<table id="restripe_table" style="border: 1px solid black" >
|
||||
<tr id="table-first"><td>first row</td></tr>
|
||||
<tr ><td>second row</td></tr>
|
||||
</table>
|
||||
</div>',
|
||||
);
|
||||
|
||||
// Demonstrates the Ajax 'settings' command. The 'settings' command has
|
||||
// nothing visual to "show", but it can be tested via SimpleTest and via
|
||||
// Firebug.
|
||||
$form['settings_command_example'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t("AJAX 'settings' command"),
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_settings_callback',
|
||||
),
|
||||
);
|
||||
|
||||
// Shows the Ajax 'add_css' command.
|
||||
$form['add_css_command_example'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t("AJAX 'add_css' command"),
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_advanced_commands_add_css_callback',
|
||||
),
|
||||
);
|
||||
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Submit'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}.
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_forms_test\Form\AjaxFormsTestLazyLoadForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_forms_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form builder: Builds a form that triggers a simple AJAX callback.
|
||||
*/
|
||||
class AjaxFormsTestLazyLoadForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_forms_test_lazy_load_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
// We attach a JavaScript setting, so that one of the generated AJAX
|
||||
// commands will be a settings command. We can then check the settings
|
||||
// command to ensure that the 'currentPath' setting is not part
|
||||
// of the Ajax response.
|
||||
$form['#attached']['drupalSettings']['test'] = 'currentPathUpdate';
|
||||
$form['add_files'] = array(
|
||||
'#title' => $this->t('Add files'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => FALSE,
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Submit'),
|
||||
'#ajax' => array(
|
||||
'wrapper' => 'ajax-forms-test-lazy-load-ajax-wrapper',
|
||||
'callback' => 'ajax_forms_test_lazy_load_form_ajax',
|
||||
),
|
||||
'#prefix' => '<div id="ajax-forms-test-lazy-load-ajax-wrapper"></div>',
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_forms_test\Form\AjaxFormsTestSimpleForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_forms_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\ajax_forms_test\Callbacks;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form builder: Builds a form that triggers a simple AJAX callback.
|
||||
*/
|
||||
class AjaxFormsTestSimpleForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_forms_test_simple_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$object = new Callbacks();
|
||||
|
||||
$form = array();
|
||||
$form['select'] = array(
|
||||
'#title' => $this->t('Color'),
|
||||
'#type' => 'select',
|
||||
'#options' => array(
|
||||
'red' => 'red',
|
||||
'green' => 'green',
|
||||
'blue' => 'blue'),
|
||||
'#ajax' => array(
|
||||
'callback' => array($object, 'selectCallback'),
|
||||
),
|
||||
'#suffix' => '<div id="ajax_selected_color">No color yet selected</div>',
|
||||
);
|
||||
|
||||
$form['checkbox'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Test checkbox'),
|
||||
'#ajax' => array(
|
||||
'callback' => array($object, 'checkboxCallback'),
|
||||
),
|
||||
'#suffix' => '<div id="ajax_checkbox_value">No action yet</div>',
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('submit'),
|
||||
);
|
||||
|
||||
// This is for testing invalid callbacks that should return a 500 error in
|
||||
// \Drupal\system\FormAjaxController::content().
|
||||
$invalid_callbacks = array(
|
||||
'null' => NULL,
|
||||
'empty' => '',
|
||||
'nonexistent' => 'some_function_that_does_not_exist',
|
||||
);
|
||||
foreach ($invalid_callbacks as $key => $value) {
|
||||
$form['select_' . $key . '_callback'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Test %key callbacks', array('%key' => $key)),
|
||||
'#options' => array('red' => 'red'),
|
||||
'#ajax' => array('callback' => $value),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_forms_test\Form\AjaxFormsTestValidationForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_forms_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form builder: Builds a form that triggers a simple AJAX callback.
|
||||
*/
|
||||
class AjaxFormsTestValidationForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_forms_test_validation_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['drivertext'] = array(
|
||||
'#title' => $this->t('AJAX-enabled textfield.'),
|
||||
'#description' => $this->t("When this one AJAX-triggers and the spare required field is empty, you should not get an error."),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $form_state->getValue('drivertext', ''),
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_validation_form_callback',
|
||||
'wrapper' => 'message_area',
|
||||
'method' => 'replace',
|
||||
),
|
||||
'#suffix' => '<div id="message_area"></div>',
|
||||
);
|
||||
|
||||
$form['drivernumber'] = array(
|
||||
'#title' => $this->t('AJAX-enabled number field.'),
|
||||
'#description' => $this->t("When this one AJAX-triggers and the spare required field is empty, you should not get an error."),
|
||||
'#type' => 'number',
|
||||
'#default_value' => $form_state->getValue('drivernumber', ''),
|
||||
'#ajax' => array(
|
||||
'callback' => 'ajax_forms_test_validation_number_form_callback',
|
||||
'wrapper' => 'message_area_number',
|
||||
'method' => 'replace',
|
||||
),
|
||||
'#suffix' => '<div id="message_area_number"></div>',
|
||||
);
|
||||
|
||||
$form['spare_required_field'] = array(
|
||||
'#title' => $this->t("Spare Required Field"),
|
||||
'#type' => 'textfield',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Submit'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
drupal_set_message($this->t("Validation form submitted"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_forms_test\Plugin\Block\AjaxFormBlock.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_forms_test\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides an AJAX form block.
|
||||
*
|
||||
* @Block(
|
||||
* id = "ajax_forms_test_block",
|
||||
* admin_label = @Translation("AJAX test form"),
|
||||
* category = @Translation("Forms")
|
||||
* )
|
||||
*/
|
||||
class AjaxFormBlock extends BlockBase implements FormInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The form builder.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $formBuilder;
|
||||
|
||||
/**
|
||||
* Constructs a new AjaxFormBlock.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, FormBuilderInterface $form_builder) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->formBuilder = $form_builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('form_builder')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return $this->formBuilder->getForm($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_forms_test_block';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['test1'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Test 1'),
|
||||
'#required' => TRUE,
|
||||
'#options' => [
|
||||
'option1' => $this->t('Option 1'),
|
||||
'option2' => $this->t('Option 2'),
|
||||
],
|
||||
'#ajax' => [
|
||||
'callback' => '::updateOptions',
|
||||
'wrapper' => 'edit-test1-wrapper',
|
||||
],
|
||||
'#prefix' => '<div id="edit-test1-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
];
|
||||
$form['actions'] = [
|
||||
'#type' => 'actions',
|
||||
];
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Submit'),
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the options of a select list.
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*
|
||||
* @return array
|
||||
* The updated form element.
|
||||
*/
|
||||
public function updateOptions(array $form, FormStateInterface $form_state) {
|
||||
$form['test1']['#options']['option1'] = $this->t('Option 1!!!');
|
||||
$form['test1']['#options'] += [
|
||||
'option3' => $this->t('Option 3'),
|
||||
'option4' => $this->t('Option 4'),
|
||||
];
|
||||
return $form['test1'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
drupal_set_message('Submission successful.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
name: 'AJAX Test'
|
||||
type: module
|
||||
description: 'Support module for AJAX framework tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- contact
|
|
@ -0,0 +1,23 @@
|
|||
order:
|
||||
drupalSettings:
|
||||
ajax: test
|
||||
dependencies:
|
||||
- ajax_test/order-css-command
|
||||
- ajax_test/order-footer-js-command
|
||||
- ajax_test/order-header-js-command
|
||||
|
||||
order-css-command:
|
||||
css:
|
||||
theme:
|
||||
# Two CSS files (order should remain the same).
|
||||
a.css: {}
|
||||
b.css: {}
|
||||
|
||||
order-footer-js-command:
|
||||
js:
|
||||
footer.js: {}
|
||||
|
||||
order-header-js-command:
|
||||
header: true
|
||||
js:
|
||||
header.js: {}
|
|
@ -0,0 +1,52 @@
|
|||
ajax_test.dialog_contents:
|
||||
path: '/ajax-test/dialog-contents'
|
||||
defaults:
|
||||
_title: 'AJAX Dialog contents routing'
|
||||
_controller: '\Drupal\ajax_test\Controller\AjaxTestController::dialogContents'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_test.dialog_form:
|
||||
path: '/ajax-test/dialog-form'
|
||||
defaults:
|
||||
_title: 'Ajax Form contents'
|
||||
_form: '\Drupal\ajax_test\Form\AjaxTestForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_test.dialog:
|
||||
path: '/ajax-test/dialog'
|
||||
defaults:
|
||||
_controller: '\Drupal\ajax_test\Controller\AjaxTestController::dialog'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_test.dialog_close:
|
||||
path: '/ajax-test/dialog-close'
|
||||
defaults:
|
||||
_controller: '\Drupal\ajax_test\Controller\AjaxTestController::dialogClose'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_test.render:
|
||||
path: '/ajax-test/render'
|
||||
defaults:
|
||||
_controller: '\Drupal\ajax_test\Controller\AjaxTestController::render'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_test.order:
|
||||
path: '/ajax-test/order'
|
||||
defaults:
|
||||
_controller: '\Drupal\ajax_test\Controller\AjaxTestController::order'
|
||||
options:
|
||||
_theme: ajax_base_page
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
ajax_test.render_error:
|
||||
path: '/ajax-test/render-error'
|
||||
defaults:
|
||||
_controller: '\Drupal\ajax_test\Controller\AjaxTestController::renderError'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_test\Controller\AjaxTestController.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_test\Controller;
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\AlertCommand;
|
||||
use Drupal\Core\Ajax\CloseDialogCommand;
|
||||
use Drupal\Core\Ajax\HtmlCommand;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Provides content for dialog tests.
|
||||
*/
|
||||
class AjaxTestController {
|
||||
|
||||
/**
|
||||
* Example content for dialog testing.
|
||||
*
|
||||
* @return array
|
||||
* Renderable array of AJAX dialog contents.
|
||||
*/
|
||||
public static function dialogContents() {
|
||||
// This is a regular render array; the keys do not have special meaning.
|
||||
$content = array(
|
||||
'#title' => 'AJAX Dialog contents',
|
||||
'content' => array(
|
||||
'#markup' => 'Example message',
|
||||
),
|
||||
'cancel' => array(
|
||||
'#type' => 'link',
|
||||
'#title' => 'Cancel',
|
||||
'#url' => Url::fromRoute('<front>'),
|
||||
'#attributes' => array(
|
||||
// This is a special class to which JavaScript assigns dialog closing
|
||||
// behavior.
|
||||
'class' => array('dialog-cancel'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a render array that will be rendered by AjaxRenderer.
|
||||
*
|
||||
* Ensures that \Drupal\Core\Ajax\AjaxResponse::ajaxRender()
|
||||
* incorporates JavaScript settings generated during the page request by
|
||||
* adding a dummy setting.
|
||||
*/
|
||||
public function render() {
|
||||
return [
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'core/drupalSettings',
|
||||
],
|
||||
'drupalSettings' => [
|
||||
'ajax' => 'test',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an AjaxResponse; settings command set last.
|
||||
*
|
||||
* Helps verifying AjaxResponse reorders commands to ensure correct execution.
|
||||
*/
|
||||
public function order() {
|
||||
$response = new AjaxResponse();
|
||||
// HTML insertion command.
|
||||
$response->addCommand(new HtmlCommand('body', 'Hello, world!'));
|
||||
$build['#attached']['library'][] = 'ajax_test/order';
|
||||
$response->setAttachments($build['#attached']);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an AjaxResponse with alert command.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request object.
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
* The JSON response object.
|
||||
*/
|
||||
public function renderError(Request $request) {
|
||||
$message = '';
|
||||
$query = $request->query;
|
||||
if ($query->has('message')) {
|
||||
$message = $query->get('message');
|
||||
}
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new AlertCommand($message));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a render array of form elements and links for dialog.
|
||||
*/
|
||||
public function dialog() {
|
||||
// Add two wrapper elements for testing non-modal dialogs. Modal dialogs use
|
||||
// the global drupal-modal wrapper by default.
|
||||
$build['dialog_wrappers'] = array('#markup' => '<div id="ajax-test-dialog-wrapper-1"></div><div id="ajax-test-dialog-wrapper-2"></div>');
|
||||
|
||||
// Dialog behavior applied to a button.
|
||||
$build['form'] = \Drupal::formBuilder()->getForm('Drupal\ajax_test\Form\AjaxTestDialogForm');
|
||||
|
||||
// Dialog behavior applied to a #type => 'link'.
|
||||
$build['link'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => 'Link 1 (modal)',
|
||||
'#url' => Url::fromRoute('ajax_test.dialog_contents'),
|
||||
'#attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
),
|
||||
);
|
||||
|
||||
// Dialog behavior applied to links rendered by links.html.twig.
|
||||
$build['links'] = array(
|
||||
'#theme' => 'links',
|
||||
'#links' => array(
|
||||
'link2' => array(
|
||||
'title' => 'Link 2 (modal)',
|
||||
'url' => Url::fromRoute('ajax_test.dialog_contents'),
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => json_encode(array(
|
||||
'width' => 400,
|
||||
))
|
||||
),
|
||||
),
|
||||
'link3' => array(
|
||||
'title' => 'Link 3 (non-modal)',
|
||||
'url' => Url::fromRoute('ajax_test.dialog_contents'),
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'dialog',
|
||||
'data-dialog-options' => json_encode(array(
|
||||
'target' => 'ajax-test-dialog-wrapper-1',
|
||||
'width' => 800,
|
||||
))
|
||||
),
|
||||
),
|
||||
'link4' => array(
|
||||
'title' => 'Link 4 (close non-modal if open)',
|
||||
'url' => Url::fromRoute('ajax_test.dialog_close'),
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
),
|
||||
),
|
||||
'link5' => array(
|
||||
'title' => 'Link 5 (form)',
|
||||
'url' => Url::fromRoute('ajax_test.dialog_form'),
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
),
|
||||
),
|
||||
'link6' => array(
|
||||
'title' => 'Link 6 (entity form)',
|
||||
'url' => Url::fromRoute('contact.form_add'),
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => json_encode(array(
|
||||
'width' => 800,
|
||||
'height' => 500,
|
||||
))
|
||||
),
|
||||
),
|
||||
'link7' => array(
|
||||
'title' => 'Link 7 (non-modal, no target)',
|
||||
'url' => Url::fromRoute('ajax_test.dialog_contents'),
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'dialog',
|
||||
'data-dialog-options' => json_encode(array(
|
||||
'width' => 800,
|
||||
))
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an AjaxResponse with command to close dialog.
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
* The JSON response object.
|
||||
*/
|
||||
public function dialogClose() {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new CloseDialogCommand('#ajax-test-dialog-wrapper-1'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_test\Form\AjaxTestDialogForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_test\Form;
|
||||
|
||||
use Drupal\ajax_test\Controller\AjaxTestController;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
use Drupal\Core\Ajax\OpenDialogCommand;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Dummy form for testing DialogRenderer with _form routes.
|
||||
*/
|
||||
class AjaxTestDialogForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_test_dialog_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
// In order to use WebTestBase::drupalPostAjaxForm() to POST from a link, we need
|
||||
// to have a dummy field we can set in WebTestBase::drupalPostForm() else it won't
|
||||
// submit anything.
|
||||
$form['textfield'] = array(
|
||||
'#type' => 'hidden'
|
||||
);
|
||||
$form['button1'] = array(
|
||||
'#type' => 'submit',
|
||||
'#name' => 'button1',
|
||||
'#value' => 'Button 1 (modal)',
|
||||
'#ajax' => array(
|
||||
'callback' => '::modal',
|
||||
),
|
||||
);
|
||||
$form['button2'] = array(
|
||||
'#type' => 'submit',
|
||||
'#name' => 'button2',
|
||||
'#value' => 'Button 2 (non-modal)',
|
||||
'#ajax' => array(
|
||||
'callback' => '::nonModal',
|
||||
),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$form_state->setRedirect('ajax_test.dialog_contents');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AJAX callback handler for AjaxTestDialogForm.
|
||||
*/
|
||||
public function modal(&$form, FormStateInterface $form_state) {
|
||||
return $this->dialog(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback handler for AjaxTestDialogForm.
|
||||
*/
|
||||
public function nonModal(&$form, FormStateInterface $form_state) {
|
||||
return $this->dialog(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Util to render dialog in ajax callback.
|
||||
*
|
||||
* @param bool $is_modal
|
||||
* (optional) TRUE if modal, FALSE if plain dialog. Defaults to FALSE.
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
* An ajax response object.
|
||||
*/
|
||||
protected function dialog($is_modal = FALSE) {
|
||||
$content = AjaxTestController::dialogContents();
|
||||
$response = new AjaxResponse();
|
||||
$title = $this->t('AJAX Dialog contents');
|
||||
|
||||
// Attach the library necessary for using the Open(Modal)DialogCommand and
|
||||
// set the attachments for this Ajax response.
|
||||
$content['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
|
||||
if ($is_modal) {
|
||||
$response->addCommand(new OpenModalDialogCommand($title, $content));
|
||||
}
|
||||
else {
|
||||
$selector = '#ajax-test-dialog-wrapper-1';
|
||||
$response->addCommand(new OpenDialogCommand($selector, $title, $content));
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ajax_test\Form\AjaxTestForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\ajax_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Dummy form for testing DialogRenderer with _form routes.
|
||||
*/
|
||||
class AjaxTestForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ajax_test_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
|
||||
$form['#action'] = \Drupal::url('ajax_test.dialog');
|
||||
|
||||
$form['description'] = array(
|
||||
'#markup' => '<p>' . $this->t("Ajax Form contents description.") . '</p>',
|
||||
);
|
||||
|
||||
$form['actions'] = array(
|
||||
'#type' => 'actions',
|
||||
);
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Do it'),
|
||||
);
|
||||
$form['actions']['preview'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Preview'),
|
||||
// No regular submit-handler. This form only works via JavaScript.
|
||||
'#submit' => array(),
|
||||
'#ajax' => array(
|
||||
// This means the ::preview() method on this class would be invoked in
|
||||
// case of a click event. However, since Drupal core's test runner only
|
||||
// is able to execute PHP, not JS, there is no point in actually
|
||||
// implementing this method, because we can never let it be called from
|
||||
// JS; we'd have to manually call it from PHP, at which point we would
|
||||
// not actually be testing it.
|
||||
// Therefore we consciously choose to not implement this method, because
|
||||
// we cannot meaningfully test it anyway.
|
||||
'callback' => '::preview',
|
||||
'event' => 'click',
|
||||
),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Batch callbacks for the Batch API tests.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Performs a simple batch operation.
|
||||
*/
|
||||
function _batch_test_callback_1($id, $sleep, &$context) {
|
||||
// No-op, but ensure the batch take a couple iterations.
|
||||
// Batch needs time to run for the test, so sleep a bit.
|
||||
usleep($sleep);
|
||||
// Track execution, and store some result for post-processing in the
|
||||
// 'finished' callback.
|
||||
batch_test_stack("op 1 id $id");
|
||||
$context['results'][1][] = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Performs a multistep batch operation.
|
||||
*/
|
||||
function _batch_test_callback_2($start, $total, $sleep, &$context) {
|
||||
// Initialize context with progress information.
|
||||
if (!isset($context['sandbox']['current'])) {
|
||||
$context['sandbox']['current'] = $start;
|
||||
$context['sandbox']['count'] = 0;
|
||||
}
|
||||
|
||||
// Process by groups of 5 (arbitrary value).
|
||||
$limit = 5;
|
||||
for ($i = 0; $i < $limit && $context['sandbox']['count'] < $total; $i++) {
|
||||
// No-op, but ensure the batch take a couple iterations.
|
||||
// Batch needs time to run for the test, so sleep a bit.
|
||||
usleep($sleep);
|
||||
// Track execution, and store some result for post-processing in the
|
||||
// 'finished' callback.
|
||||
$id = $context['sandbox']['current'] + $i;
|
||||
batch_test_stack("op 2 id $id");
|
||||
$context['results'][2][] = $id;
|
||||
|
||||
// Update progress information.
|
||||
$context['sandbox']['count']++;
|
||||
}
|
||||
$context['sandbox']['current'] += $i;
|
||||
|
||||
// Inform batch engine about progress.
|
||||
if ($context['sandbox']['count'] != $total) {
|
||||
$context['finished'] = $context['sandbox']['count'] / $total;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*/
|
||||
function _batch_test_callback_5($id, $sleep, &$context) {
|
||||
// No-op, but ensure the batch take a couple iterations.
|
||||
// Batch needs time to run for the test, so sleep a bit.
|
||||
usleep($sleep);
|
||||
// Track execution, and store some result for post-processing in the
|
||||
// 'finished' callback.
|
||||
batch_test_stack("op 5 id $id");
|
||||
$context['results'][5][] = $id;
|
||||
// This test is to test finished > 1
|
||||
$context['finished'] = 3.14;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Performs a batch operation setting up its own batch.
|
||||
*/
|
||||
function _batch_test_nested_batch_callback() {
|
||||
batch_test_stack('setting up batch 2');
|
||||
batch_set(_batch_test_batch_2());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a common 'finished' callback for batches 1 to 4.
|
||||
*/
|
||||
function _batch_test_finished_helper($batch_id, $success, $results, $operations) {
|
||||
$messages = array("results for batch $batch_id");
|
||||
if ($results) {
|
||||
foreach ($results as $op => $op_results) {
|
||||
$messages[] = 'op '. SafeMarkup::escape($op) . ': processed ' . count($op_results) . ' elements';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$messages[] = 'none';
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
// A fatal error occurred during the processing.
|
||||
$error_operation = reset($operations);
|
||||
$messages[] = t('An error occurred while processing @op with arguments:<br />@args', array('@op' => $error_operation[0], '@args' => print_r($error_operation[1], TRUE)));
|
||||
}
|
||||
|
||||
drupal_set_message(SafeMarkup::set(implode('<br>', $messages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Triggers 'finished' callback for batch 0.
|
||||
*/
|
||||
function _batch_test_finished_0($success, $results, $operations) {
|
||||
_batch_test_finished_helper(0, $success, $results, $operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Triggers 'finished' callback for batch 1.
|
||||
*/
|
||||
function _batch_test_finished_1($success, $results, $operations) {
|
||||
_batch_test_finished_helper(1, $success, $results, $operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Triggers 'finished' callback for batch 2.
|
||||
*/
|
||||
function _batch_test_finished_2($success, $results, $operations) {
|
||||
_batch_test_finished_helper(2, $success, $results, $operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Triggers 'finished' callback for batch 3.
|
||||
*/
|
||||
function _batch_test_finished_3($success, $results, $operations) {
|
||||
_batch_test_finished_helper(3, $success, $results, $operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Triggers 'finished' callback for batch 4.
|
||||
*/
|
||||
function _batch_test_finished_4($success, $results, $operations) {
|
||||
_batch_test_finished_helper(4, $success, $results, $operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Triggers 'finished' callback for batch 5.
|
||||
*/
|
||||
function _batch_test_finished_5($success, $results, $operations) {
|
||||
_batch_test_finished_helper(5, $success, $results, $operations);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Batch API test'
|
||||
type: module
|
||||
description: 'Support module for Batch API tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,46 @@
|
|||
batch_test.test_form:
|
||||
title: Simple
|
||||
route_name: batch_test.test_form
|
||||
base_route: batch_test.test_form
|
||||
|
||||
batch_test.multistep:
|
||||
title: Multistep
|
||||
route_name: batch_test.multistep
|
||||
base_route: batch_test.test_form
|
||||
weight: 1
|
||||
|
||||
batch_test.chained:
|
||||
title: Chained
|
||||
route_name: batch_test.chained
|
||||
base_route: batch_test.test_form
|
||||
weight: 2
|
||||
|
||||
batch_test.programmatic:
|
||||
title: Chained
|
||||
route_name: batch_test.programmatic
|
||||
base_route: batch_test.test_form
|
||||
weight: 3
|
||||
|
||||
batch_test.no_form:
|
||||
title: 'No form'
|
||||
route_name: batch_test.no_form
|
||||
base_route: batch_test.test_form
|
||||
weight: 4
|
||||
|
||||
batch_test.large_percentage:
|
||||
title: 'Large percentage'
|
||||
route_name: batch_test.large_percentage
|
||||
base_route: batch_test.test_form
|
||||
weight: 5
|
||||
|
||||
batch_test.nested_programmatic:
|
||||
title: 'Nested programmatic'
|
||||
route_name: batch_test.nested_programmatic
|
||||
base_route: batch_test.test_form
|
||||
weight: 6
|
||||
|
||||
batch_test.redirect:
|
||||
title: 'Redirect'
|
||||
route_name: batch_test.redirect
|
||||
base_route: batch_test.test_form
|
||||
weight: 7
|
199
core/modules/system/tests/modules/batch_test/batch_test.module
Normal file
199
core/modules/system/tests/modules/batch_test/batch_test.module
Normal file
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Helper module for the Batch API tests.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Form\FormState;
|
||||
|
||||
/**
|
||||
* Batch operation: Submits form_test_mock_form().
|
||||
*/
|
||||
function _batch_test_nested_drupal_form_submit_callback($value) {
|
||||
$form_state = (new FormState())
|
||||
->setValue('test_value', $value);
|
||||
\Drupal::formBuilder()->submitForm('Drupal\batch_test\Form\BatchTestMockForm', $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch 0: Does nothing.
|
||||
*/
|
||||
function _batch_test_batch_0() {
|
||||
$batch = array(
|
||||
'operations' => array(),
|
||||
'finished' => '_batch_test_finished_0',
|
||||
'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc',
|
||||
);
|
||||
return $batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch 1: Repeats a simple operation.
|
||||
*
|
||||
* Operations: op 1 from 1 to 10.
|
||||
*/
|
||||
function _batch_test_batch_1() {
|
||||
// Ensure the batch takes at least two iterations.
|
||||
$total = 10;
|
||||
$sleep = (1000000 / $total) * 2;
|
||||
|
||||
$operations = array();
|
||||
for ($i = 1; $i <= $total; $i++) {
|
||||
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||||
}
|
||||
$batch = array(
|
||||
'operations' => $operations,
|
||||
'finished' => '_batch_test_finished_1',
|
||||
'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc',
|
||||
);
|
||||
return $batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch 2: Performs a single multistep operation.
|
||||
*
|
||||
* Operations: op 2 from 1 to 10.
|
||||
*/
|
||||
function _batch_test_batch_2() {
|
||||
// Ensure the batch takes at least two iterations.
|
||||
$total = 10;
|
||||
$sleep = (1000000 / $total) * 2;
|
||||
|
||||
$operations = array(
|
||||
array('_batch_test_callback_2', array(1, $total, $sleep)),
|
||||
);
|
||||
$batch = array(
|
||||
'operations' => $operations,
|
||||
'finished' => '_batch_test_finished_2',
|
||||
'file' => drupal_get_path('module', 'batch_test') . '/batch_test.callbacks.inc',
|
||||
);
|
||||
return $batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch 3: Performs both single and multistep operations.
|
||||
*
|
||||
* Operations:
|
||||
* - op 1 from 1 to 5,
|
||||
* - op 2 from 1 to 5,
|
||||
* - op 1 from 6 to 10,
|
||||
* - op 2 from 6 to 10.
|
||||
*/
|
||||
function _batch_test_batch_3() {
|
||||
// Ensure the batch takes at least two iterations.
|
||||
$total = 10;
|
||||
$sleep = (1000000 / $total) * 2;
|
||||
|
||||
$operations = array();
|
||||
for ($i = 1; $i <= round($total / 2); $i++) {
|
||||
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||||
}
|
||||
$operations[] = array('_batch_test_callback_2', array(1, $total / 2, $sleep));
|
||||
for ($i = round($total / 2) + 1; $i <= $total; $i++) {
|
||||
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||||
}
|
||||
$operations[] = array('_batch_test_callback_2', array(6, $total / 2, $sleep));
|
||||
$batch = array(
|
||||
'operations' => $operations,
|
||||
'finished' => '_batch_test_finished_3',
|
||||
'file' => drupal_get_path('module', 'batch_test') . '/batch_test.callbacks.inc',
|
||||
);
|
||||
return $batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch 4: Performs a batch within a batch.
|
||||
*
|
||||
* Operations:
|
||||
* - op 1 from 1 to 5,
|
||||
* - set batch 2 (op 2 from 1 to 10, should run at the end)
|
||||
* - op 1 from 6 to 10,
|
||||
*/
|
||||
function _batch_test_batch_4() {
|
||||
// Ensure the batch takes at least two iterations.
|
||||
$total = 10;
|
||||
$sleep = (1000000 / $total) * 2;
|
||||
|
||||
$operations = array();
|
||||
for ($i = 1; $i <= round($total / 2); $i++) {
|
||||
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||||
}
|
||||
$operations[] = array('_batch_test_nested_batch_callback', array());
|
||||
for ($i = round($total / 2) + 1; $i <= $total; $i++) {
|
||||
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||||
}
|
||||
$batch = array(
|
||||
'operations' => $operations,
|
||||
'finished' => '_batch_test_finished_4',
|
||||
'file' => drupal_get_path('module', 'batch_test') . '/batch_test.callbacks.inc',
|
||||
);
|
||||
return $batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch 5: Repeats a simple operation.
|
||||
*
|
||||
* Operations: op 1 from 1 to 10.
|
||||
*/
|
||||
function _batch_test_batch_5() {
|
||||
// Ensure the batch takes at least two iterations.
|
||||
$total = 10;
|
||||
$sleep = (1000000 / $total) * 2;
|
||||
|
||||
$operations = array();
|
||||
for ($i = 1; $i <= $total; $i++) {
|
||||
$operations[] = array('_batch_test_callback_5', array($i, $sleep));
|
||||
}
|
||||
$batch = array(
|
||||
'operations' => $operations,
|
||||
'finished' => '_batch_test_finished_5',
|
||||
'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc',
|
||||
);
|
||||
return $batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Tests the progress page theme.
|
||||
*/
|
||||
function _batch_test_theme_callback() {
|
||||
// Because drupalGet() steps through the full progressive batch before
|
||||
// returning control to the test function, we cannot test that the correct
|
||||
// theme is being used on the batch processing page by viewing that page
|
||||
// directly. Instead, we save the theme being used in a variable here, so
|
||||
// that it can be loaded and inspected in the thread running the test.
|
||||
$theme = \Drupal::theme()->getActiveTheme()->getName();
|
||||
batch_test_stack($theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the title on the progress page by performing a batch callback.
|
||||
*/
|
||||
function _batch_test_title_callback() {
|
||||
// Because drupalGet() steps through the full progressive batch before
|
||||
// returning control to the test function, we cannot test that the correct
|
||||
// title is being used on the batch processing page by viewing that page
|
||||
// directly. Instead, we save the title being used in a variable here, so
|
||||
// that it can be loaded and inspected in the thread running the test.
|
||||
$request = \Drupal::request();
|
||||
$route_match = \Drupal::routeMatch();
|
||||
$title = \Drupal::service('title_resolver')->getTitle($request, $route_match->getRouteObject());
|
||||
batch_test_stack($title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function: Stores or retrieves traced execution data.
|
||||
*/
|
||||
function batch_test_stack($data = NULL, $reset = FALSE) {
|
||||
if ($reset) {
|
||||
\Drupal::state()->delete('batch_test.stack');
|
||||
}
|
||||
if (!isset($data)) {
|
||||
return \Drupal::state()->get('batch_test.stack');
|
||||
}
|
||||
$stack = \Drupal::state()->get('batch_test.stack');
|
||||
$stack[] = $data;
|
||||
\Drupal::state()->set('batch_test.stack', $stack);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
batch_test.redirect:
|
||||
path: '/batch-test/redirect'
|
||||
defaults:
|
||||
_controller: '\Drupal\batch_test\Controller\BatchTestController::testRedirect'
|
||||
_title: 'Redirect'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.large_percentage:
|
||||
path: '/batch-test/large-percentage'
|
||||
defaults:
|
||||
_controller: '\Drupal\batch_test\Controller\BatchTestController::testLargePercentage'
|
||||
_title: 'Simple page with batch over 100% complete'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.nested_programmatic:
|
||||
path: '/batch-test/nested-programmatic/{value}'
|
||||
defaults:
|
||||
_controller: '\Drupal\batch_test\Controller\BatchTestController::testNestedDrupalFormSubmit'
|
||||
_title: 'Nested programmatic'
|
||||
value: '1'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.no_form:
|
||||
path: '/batch-test/no-form'
|
||||
defaults:
|
||||
_controller: '\Drupal\batch_test\Controller\BatchTestController::testNoForm'
|
||||
_title: 'Simple page'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.test_form:
|
||||
path: '/batch-test'
|
||||
defaults:
|
||||
_form: '\Drupal\batch_test\Form\BatchTestSimpleForm'
|
||||
_title: 'Batch test'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.multistep:
|
||||
path: '/batch-test/multistep'
|
||||
defaults:
|
||||
_form: '\Drupal\batch_test\Form\BatchTestMultiStepForm'
|
||||
_title: 'Multistep'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.chained:
|
||||
path: '/batch-test/chained'
|
||||
defaults:
|
||||
_form: '\Drupal\batch_test\Form\BatchTestChainedForm'
|
||||
_title: 'Chained'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.programmatic:
|
||||
path: '/batch-test/programmatic/{value}'
|
||||
defaults:
|
||||
_controller: '\Drupal\batch_test\Controller\BatchTestController::testProgrammatic'
|
||||
_title: 'Programmatic'
|
||||
value: '1'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.test_theme:
|
||||
path: '/admin/batch-test/test-theme'
|
||||
defaults:
|
||||
_controller: '\Drupal\batch_test\Controller\BatchTestController::testThemeBatch'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
batch_test.test_title:
|
||||
path: '/batch-test/test-title'
|
||||
defaults:
|
||||
_controller: '\Drupal\batch_test\Controller\BatchTestController::testTitleBatch'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\batch_test\Controller\BatchTestController.
|
||||
*/
|
||||
|
||||
namespace Drupal\batch_test\Controller;
|
||||
|
||||
use Drupal\Core\Form\FormState;
|
||||
|
||||
/**
|
||||
* Controller routines for batch tests.
|
||||
*/
|
||||
class BatchTestController {
|
||||
|
||||
/**
|
||||
* Redirects successfully.
|
||||
*
|
||||
* @return array
|
||||
* Render array containing success message.
|
||||
*/
|
||||
public function testRedirect() {
|
||||
return array(
|
||||
'success' => array(
|
||||
'#markup' => 'Redirection successful.',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a batch process without a form submission.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
|
||||
* A redirect response if the batch is progressive. No return value otherwise.
|
||||
*/
|
||||
public function testLargePercentage() {
|
||||
batch_test_stack(NULL, TRUE);
|
||||
|
||||
batch_set(_batch_test_batch_5());
|
||||
return batch_process('batch-test/redirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits a form within a batch programmatically.
|
||||
*
|
||||
* @param int $value
|
||||
* Some value passed to a custom batch callback.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
|
||||
* A redirect response if the batch is progressive. No return value otherwise.
|
||||
*/
|
||||
public function testNestedDrupalFormSubmit($value = 1) {
|
||||
// Set the batch and process it.
|
||||
$batch['operations'] = array(
|
||||
array('_batch_test_nested_drupal_form_submit_callback', array($value)),
|
||||
);
|
||||
batch_set($batch);
|
||||
return batch_process('batch-test/redirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a batch process without a form submission.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
|
||||
* A redirect response if the batch is progressive. No return value otherwise.
|
||||
*/
|
||||
public function testNoForm() {
|
||||
batch_test_stack(NULL, TRUE);
|
||||
|
||||
batch_set(_batch_test_batch_1());
|
||||
return batch_process('batch-test/redirect');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the 'Chained' form programmatically.
|
||||
*
|
||||
* Programmatic form: the page submits the 'Chained' form through
|
||||
* \Drupal::formBuilder()->submitForm().
|
||||
*
|
||||
* @param int $value
|
||||
* Some value passed to a the chained form.
|
||||
*
|
||||
* @return array
|
||||
* Render array containing markup.
|
||||
*/
|
||||
function testProgrammatic($value = 1) {
|
||||
$form_state = (new FormState())->setValues([
|
||||
'value' => $value,
|
||||
]);
|
||||
\Drupal::formBuilder()->submitForm('Drupal\batch_test\Form\BatchTestChainedForm', $form_state);
|
||||
return array(
|
||||
'success' => array(
|
||||
'#markup' => 'Got out of a programmatic batched form.',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a batch for testing theme used on the progress page.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
|
||||
* A redirect response if the batch is progressive. No return value otherwise.
|
||||
*/
|
||||
public function testThemeBatch() {
|
||||
batch_test_stack(NULL, TRUE);
|
||||
$batch = array(
|
||||
'operations' => array(
|
||||
array('_batch_test_theme_callback', array()),
|
||||
),
|
||||
);
|
||||
batch_set($batch);
|
||||
return batch_process('batch-test/redirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a batch for testing the title shown on the progress page.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
|
||||
* A redirect response if the batch is progressive. No return value otherwise.
|
||||
*/
|
||||
public function testTitleBatch() {
|
||||
batch_test_stack(NULL, TRUE);
|
||||
$batch = [
|
||||
'title' => 'Batch Test',
|
||||
'operations' => [
|
||||
['_batch_test_title_callback', []],
|
||||
],
|
||||
];
|
||||
batch_set($batch);
|
||||
return batch_process('batch-test/redirect');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\batch_test\Form\BatchTestChainedForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\batch_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Generate form of id batch_test_chained_form.
|
||||
*/
|
||||
class BatchTestChainedForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'batch_test_chained_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
// This value is used to test that $form_state persists through batched
|
||||
// submit handlers.
|
||||
$form['value'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => 'Value',
|
||||
'#default_value' => 1,
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => 'Submit',
|
||||
);
|
||||
$form['#submit'] = array(
|
||||
'Drupal\batch_test\Form\BatchTestChainedForm::batchTestChainedFormSubmit1',
|
||||
'Drupal\batch_test\Form\BatchTestChainedForm::batchTestChainedFormSubmit2',
|
||||
'Drupal\batch_test\Form\BatchTestChainedForm::batchTestChainedFormSubmit3',
|
||||
'Drupal\batch_test\Form\BatchTestChainedForm::batchTestChainedFormSubmit4',
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler #1 for batch_test_chained_form
|
||||
*/
|
||||
public static function batchTestChainedFormSubmit1($form, FormStateInterface $form_state) {
|
||||
batch_test_stack(NULL, TRUE);
|
||||
|
||||
batch_test_stack('submit handler 1');
|
||||
batch_test_stack('value = ' . $form_state->getValue('value'));
|
||||
|
||||
$value = &$form_state->getValue('value');
|
||||
$value++;
|
||||
batch_set(_batch_test_batch_1());
|
||||
|
||||
$form_state->setRedirect('batch_test.redirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler #2 for batch_test_chained_form
|
||||
*/
|
||||
public static function batchTestChainedFormSubmit2($form, FormStateInterface $form_state) {
|
||||
batch_test_stack('submit handler 2');
|
||||
batch_test_stack('value = ' . $form_state->getValue('value'));
|
||||
|
||||
$value = &$form_state->getValue('value');
|
||||
$value++;
|
||||
batch_set(_batch_test_batch_2());
|
||||
|
||||
$form_state->setRedirect('batch_test.redirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler #3 for batch_test_chained_form
|
||||
*/
|
||||
public static function batchTestChainedFormSubmit3($form, FormStateInterface $form_state) {
|
||||
batch_test_stack('submit handler 3');
|
||||
batch_test_stack('value = ' . $form_state->getValue('value'));
|
||||
|
||||
$value = &$form_state->getValue('value');
|
||||
$value++;
|
||||
|
||||
$form_state->setRedirect('batch_test.redirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler #4 for batch_test_chained_form
|
||||
*/
|
||||
public static function batchTestChainedFormSubmit4($form, FormStateInterface $form_state) {
|
||||
batch_test_stack('submit handler 4');
|
||||
batch_test_stack('value = ' . $form_state->getValue('value'));
|
||||
|
||||
$value = &$form_state->getValue('value');
|
||||
$value++;
|
||||
batch_set(_batch_test_batch_3());
|
||||
|
||||
$form_state->setRedirect('batch_test.redirect');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\batch_test\Form\BatchTestMockForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\batch_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Generate form of id batch_test_mock_form.
|
||||
*/
|
||||
class BatchTestMockForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'batch_test_mock_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['test_value'] = array(
|
||||
'#title' => t('Test value'),
|
||||
'#type' => 'textfield',
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Submit'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
batch_test_stack('mock form submitted with value = ' . $form_state->getValue('test_value'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\batch_test\Form\BatchTestMultiStepForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\batch_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Generate form of id batch_test_multistep_form.
|
||||
*/
|
||||
class BatchTestMultiStepForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'batch_test_multistep_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$step = $form_state->get('step');
|
||||
if (empty($step)) {
|
||||
$step = 1;
|
||||
$form_state->set('step', $step);
|
||||
}
|
||||
|
||||
$form['step_display'] = array(
|
||||
'#markup' => 'step ' . $step . '<br/>',
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => 'Submit',
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
batch_test_stack(NULL, TRUE);
|
||||
|
||||
$step = $form_state->get('step');
|
||||
switch ($step) {
|
||||
case 1:
|
||||
batch_set(_batch_test_batch_1());
|
||||
break;
|
||||
case 2:
|
||||
batch_set(_batch_test_batch_2());
|
||||
break;
|
||||
}
|
||||
|
||||
if ($step < 2) {
|
||||
$form_state->set('step', ++$step);
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
|
||||
$form_state->setRedirect('batch_test.redirect');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\batch_test\Form\BatchTestSimpleForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\batch_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Generate form of id batch_test_simple_form.
|
||||
*/
|
||||
class BatchTestSimpleForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'batch_test_simple_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['batch'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => 'Choose batch',
|
||||
'#options' => array(
|
||||
'batch_0' => 'batch 0',
|
||||
'batch_1' => 'batch 1',
|
||||
'batch_2' => 'batch 2',
|
||||
'batch_3' => 'batch 3',
|
||||
'batch_4' => 'batch 4',
|
||||
),
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => 'Submit',
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
batch_test_stack(NULL, TRUE);
|
||||
|
||||
$function = '_batch_test_' . $form_state->getValue('batch');
|
||||
batch_set($function());
|
||||
|
||||
$form_state->setRedirect('batch_test.redirect');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Cache test'
|
||||
type: module
|
||||
description: 'Support module for cache system testing.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
/* This file is for testing CSS file inclusion, no contents are necessary. */
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Common Test'
|
||||
type: module
|
||||
description: 'Support module for Common tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,115 @@
|
|||
jquery.farbtastic:
|
||||
version: 0.1
|
||||
js:
|
||||
assets/vendor/farbtastic/farbtastic.js: {}
|
||||
css:
|
||||
component:
|
||||
assets/vendor/farbtastic/farbtastic.css: {}
|
||||
dependencies:
|
||||
- core/jquery
|
||||
|
||||
# Library to test CSS and JS file assets.
|
||||
files:
|
||||
js:
|
||||
foo.js: {}
|
||||
css:
|
||||
theme:
|
||||
bar.css: {}
|
||||
|
||||
# Library to test external CSS and JS file assets.
|
||||
external:
|
||||
version: 1
|
||||
js:
|
||||
http://example.com/script.js: { type: external }
|
||||
css:
|
||||
theme:
|
||||
http://example.com/stylesheet.css: { type: external }
|
||||
|
||||
# Library to test JS file asset attributes (both internal and external).
|
||||
js-attributes:
|
||||
version: 1
|
||||
js:
|
||||
deferred-internal.js: { attributes: { defer: true, bar: foo } }
|
||||
http://example.com/deferred-external.js:
|
||||
type: external
|
||||
attributes:
|
||||
foo: bar
|
||||
defer: true
|
||||
|
||||
js-header:
|
||||
header: true
|
||||
js:
|
||||
header.js: {}
|
||||
dependencies:
|
||||
- core/drupal
|
||||
|
||||
# Library to test setting cache = FALSE, to prevent aggregation.
|
||||
no-cache:
|
||||
js:
|
||||
nocache.js: { cache: false }
|
||||
|
||||
order:
|
||||
js:
|
||||
weight_-3_1.js: { weight: -3 }
|
||||
weight_0_1.js: {}
|
||||
weight_0_2.js: {}
|
||||
weight_-8_1.js: { weight: -8 }
|
||||
weight_-8_2.js: { weight: -8 }
|
||||
weight_-8_3.js: { weight: -8 }
|
||||
http://example.com/weight_-5_1.js: { type: external, weight: -5 }
|
||||
weight_-8_4.js: { weight: -8 }
|
||||
weight_-3_2.js: { weight: -3 }
|
||||
weight_0_3.js: {}
|
||||
css:
|
||||
base:
|
||||
base_weight_0_1.js: {}
|
||||
base_weight_0_2.js: {}
|
||||
base_weight_-8_1.js: { weight: -8 }
|
||||
base_weight_-101_1.js: { weight: -101 }
|
||||
layout:
|
||||
layout_weight_0_1.js: {}
|
||||
layout_weight_0_2.js: {}
|
||||
layout_weight_-8_1.js: { weight: -8 }
|
||||
layout_weight_-101_1.js: { weight: -101 }
|
||||
component:
|
||||
component_weight_0_1.js: {}
|
||||
component_weight_0_2.js: {}
|
||||
component_weight_-8_1.js: { weight: -8}
|
||||
component_weight_-101_1.js: { weight: -101}
|
||||
state:
|
||||
state_weight_0_1.js: {}
|
||||
state_weight_0_2.js: {}
|
||||
state_weight_-8_1.js: { weight: -8}
|
||||
state_weight_-101_1.js: { weight: -101}
|
||||
theme:
|
||||
theme_weight_0_1.js: {}
|
||||
theme_weight_0_2.js: {}
|
||||
theme_weight_-8_1.js: { weight: -8}
|
||||
theme_weight_-101_1.js: { weight: -101}
|
||||
|
||||
weight:
|
||||
css:
|
||||
theme:
|
||||
first.css: {}
|
||||
lighter.js: { weight: -1 }
|
||||
js:
|
||||
first.js: {}
|
||||
lighter.js: { weight: -1 }
|
||||
before-jquery.js: { weight: -21 }
|
||||
|
||||
browsers:
|
||||
js:
|
||||
old-ie.js:
|
||||
browsers:
|
||||
'IE': 'lte IE 8'
|
||||
'!IE': false
|
||||
no-ie.js:
|
||||
browsers:
|
||||
IE: false
|
||||
|
||||
querystring:
|
||||
js:
|
||||
querystring.js?arg1=value1&arg2=value2: {}
|
||||
css:
|
||||
theme:
|
||||
querystring.css?arg1=value1&arg2=value2: {}
|
280
core/modules/system/tests/modules/common_test/common_test.module
Normal file
280
core/modules/system/tests/modules/common_test/common_test.module
Normal file
|
@ -0,0 +1,280 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Helper module for the Common tests.
|
||||
*/
|
||||
|
||||
use \Drupal\Core\Asset\AttachedAssetsInterface;
|
||||
|
||||
/**
|
||||
* Applies #printed to an element to help test #pre_render.
|
||||
*/
|
||||
function common_test_drupal_render_printing_pre_render($elements) {
|
||||
$elements['#printed'] = TRUE;
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_TYPE_alter().
|
||||
*/
|
||||
function common_test_drupal_alter_alter(&$data, &$arg2 = NULL, &$arg3 = NULL) {
|
||||
// Alter first argument.
|
||||
if (is_array($data)) {
|
||||
$data['foo'] = 'Drupal';
|
||||
}
|
||||
elseif (is_object($data)) {
|
||||
$data->foo = 'Drupal';
|
||||
}
|
||||
// Alter second argument, if present.
|
||||
if (isset($arg2)) {
|
||||
if (is_array($arg2)) {
|
||||
$arg2['foo'] = 'Drupal';
|
||||
}
|
||||
elseif (is_object($arg2)) {
|
||||
$arg2->foo = 'Drupal';
|
||||
}
|
||||
}
|
||||
// Try to alter third argument, if present.
|
||||
if (isset($arg3)) {
|
||||
if (is_array($arg3)) {
|
||||
$arg3['foo'] = 'Drupal';
|
||||
}
|
||||
elseif (is_object($arg3)) {
|
||||
$arg3->foo = 'Drupal';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_TYPE_alter() on behalf of Bartik theme.
|
||||
*
|
||||
* Same as common_test_drupal_alter_alter(), but here, we verify that themes
|
||||
* can also alter and come last.
|
||||
*/
|
||||
function bartik_drupal_alter_alter(&$data, &$arg2 = NULL, &$arg3 = NULL) {
|
||||
// Alter first argument.
|
||||
if (is_array($data)) {
|
||||
$data['foo'] .= ' theme';
|
||||
}
|
||||
elseif (is_object($data)) {
|
||||
$data->foo .= ' theme';
|
||||
}
|
||||
// Alter second argument, if present.
|
||||
if (isset($arg2)) {
|
||||
if (is_array($arg2)) {
|
||||
$arg2['foo'] .= ' theme';
|
||||
}
|
||||
elseif (is_object($arg2)) {
|
||||
$arg2->foo .= ' theme';
|
||||
}
|
||||
}
|
||||
// Try to alter third argument, if present.
|
||||
if (isset($arg3)) {
|
||||
if (is_array($arg3)) {
|
||||
$arg3['foo'] .= ' theme';
|
||||
}
|
||||
elseif (is_object($arg3)) {
|
||||
$arg3->foo .= ' theme';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_TYPE_alter() on behalf of block module.
|
||||
*
|
||||
* This is to verify that
|
||||
* \Drupal::moduleHandler()->alter(array(TYPE1, TYPE2), ...) allows
|
||||
* hook_module_implements_alter() to affect the order in which module
|
||||
* implementations are executed.
|
||||
*/
|
||||
function block_drupal_alter_foo_alter(&$data, &$arg2 = NULL, &$arg3 = NULL) {
|
||||
$data['foo'] .= ' block';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_module_implements_alter().
|
||||
*
|
||||
* @see block_drupal_alter_foo_alter()
|
||||
*/
|
||||
function common_test_module_implements_alter(&$implementations, $hook) {
|
||||
// For
|
||||
// \Drupal::moduleHandler()->alter(array('drupal_alter', 'drupal_alter_foo'), ...),
|
||||
// make the block module implementations run after all the other modules. Note
|
||||
// that when \Drupal::moduleHandler->alter() is called with an array of types,
|
||||
// the first type is considered primary and controls the module order.
|
||||
if ($hook == 'drupal_alter_alter' && isset($implementations['block'])) {
|
||||
$group = $implementations['block'];
|
||||
unset($implementations['block']);
|
||||
$implementations['block'] = $group;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function common_test_theme() {
|
||||
return array(
|
||||
'common_test_foo' => array(
|
||||
'variables' => array('foo' => 'foo', 'bar' => 'bar'),
|
||||
),
|
||||
'common_test_render_element' => array(
|
||||
'render element' => 'foo',
|
||||
),
|
||||
'common_test_empty' => array(
|
||||
'variables' => array('foo' => 'foo'),
|
||||
'function' => 'theme_common_test_empty',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a theme function for drupal_render().
|
||||
*/
|
||||
function theme_common_test_foo($variables) {
|
||||
return $variables['foo'] . $variables['bar'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns an empty string.
|
||||
*/
|
||||
function theme_common_test_empty($variables) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements MODULE_preprocess().
|
||||
*
|
||||
* @see RenderTest::testDrupalRenderThemePreprocessAttached()
|
||||
*/
|
||||
function common_test_preprocess(&$variables, $hook) {
|
||||
if (!\Drupal::state()->get('theme_preprocess_attached_test', FALSE)) {
|
||||
return;
|
||||
}
|
||||
$variables['#attached']['library'][] = 'test/generic_preprocess';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements MODULE_preprocess_HOOK().
|
||||
*
|
||||
* @see RenderTest::testDrupalRenderThemePreprocessAttached()
|
||||
*/
|
||||
function common_test_preprocess_common_test_render_element(&$variables) {
|
||||
if (!\Drupal::state()->get('theme_preprocess_attached_test', FALSE)) {
|
||||
return;
|
||||
}
|
||||
$variables['#attached']['library'][] = 'test/specific_preprocess';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_library_info_build().
|
||||
*/
|
||||
function common_test_library_info_build() {
|
||||
$libraries = [];
|
||||
if (\Drupal::state()->get('common_test.library_info_build_test')) {
|
||||
$libraries['dynamic_library'] = [
|
||||
'version' => '1.0',
|
||||
'css' => [
|
||||
'base' => [
|
||||
'common_test.css' => [],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
return $libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_library_info_alter().
|
||||
*/
|
||||
function common_test_library_info_alter(&$libraries, $module) {
|
||||
if ($module == 'core' && isset($libraries['jquery.farbtastic'])) {
|
||||
// Change the version of Farbtastic to 0.0.
|
||||
$libraries['jquery.farbtastic']['version'] = '0.0';
|
||||
// Make Farbtastic depend on jQuery Form to test library dependencies.
|
||||
$libraries['jquery.farbtastic']['dependencies'][] = 'core/jquery.form';
|
||||
}
|
||||
|
||||
// Alter the dynamically registered library definition.
|
||||
if ($module == 'common_test' && isset($libraries['dynamic_library'])) {
|
||||
$libraries['dynamic_library']['dependencies'] = [
|
||||
'core/jquery',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_cron().
|
||||
*
|
||||
* System module should handle if a module does not catch an exception and keep
|
||||
* cron going.
|
||||
*
|
||||
* @see common_test_cron_helper()
|
||||
*
|
||||
*/
|
||||
function common_test_cron() {
|
||||
throw new Exception(t('Uncaught exception'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_page_attachments().
|
||||
*
|
||||
* @see \Drupal\system\Tests\Common\PageRenderTest::assertPageRenderHookExceptions()
|
||||
*/
|
||||
function common_test_page_attachments(array &$page) {
|
||||
$page['#attached']['library'][] = 'core/foo';
|
||||
$page['#attached']['library'][] = 'core/bar';
|
||||
$page['#cache']['tags'] = ['example'];
|
||||
$page['#cache']['contexts'] = ['user.permissions'];
|
||||
|
||||
if (\Drupal::state()->get('common_test.hook_page_attachments.descendant_attached', FALSE)) {
|
||||
$page['content']['#attached']['library'][] = 'core/jquery';
|
||||
}
|
||||
|
||||
if (\Drupal::state()->get('common_test.hook_page_attachments.render_array', FALSE)) {
|
||||
$page['something'] = [
|
||||
'#markup' => 'test',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_page_attachments_alter().
|
||||
*
|
||||
* @see \Drupal\system\Tests\Common\PageRenderTest::assertPageRenderHookExceptions()
|
||||
*/
|
||||
function common_test_page_attachments_alter(array &$page) {
|
||||
// Remove a library that was added in common_test_page_attachments(), to test
|
||||
// that this hook can do what it claims to do.
|
||||
if (isset($page['#attached']['library']) && ($index = array_search('core/bar', $page['#attached']['library'])) && $index !== FALSE) {
|
||||
unset($page['#attached']['library'][$index]);
|
||||
}
|
||||
$page['#attached']['library'][] = 'core/baz';
|
||||
$page['#cache']['tags'] = ['example'];
|
||||
$page['#cache']['contexts'] = ['user.permissions'];
|
||||
|
||||
if (\Drupal::state()->get('common_test.hook_page_attachments_alter.descendant_attached', FALSE)) {
|
||||
$page['content']['#attached']['library'][] = 'core/jquery';
|
||||
}
|
||||
|
||||
if (\Drupal::state()->get('common_test.hook_page_attachments_alter.render_array', FALSE)) {
|
||||
$page['something'] = [
|
||||
'#markup' => 'test',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_js_settings_alter().
|
||||
*
|
||||
* @see \Drupal\system\Tests\Common\JavaScriptTest::testHeaderSetting()
|
||||
*/
|
||||
function common_test_js_settings_alter(&$settings, AttachedAssetsInterface $assets) {
|
||||
// Modify an existing setting.
|
||||
if (array_key_exists('pluralDelimiter', $settings)) {
|
||||
$settings['pluralDelimiter'] = '☃';
|
||||
}
|
||||
|
||||
// Add a setting.
|
||||
$settings['foo'] = 'bar';
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
/* This file is for testing CSS file inclusion, no contents are necessary. */
|
|
@ -0,0 +1,21 @@
|
|||
common_test.l_active_class:
|
||||
path: '/common-test/type-link-active-class'
|
||||
defaults:
|
||||
_controller: '\Drupal\common_test\Controller\CommonTestController::typeLinkActiveClass'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
common_test.destination:
|
||||
path: '/common-test/destination'
|
||||
defaults:
|
||||
_controller: '\Drupal\common_test\Controller\CommonTestController::destination'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
common_test.js_and_css_querystring:
|
||||
path: '/common-test/query-string'
|
||||
defaults:
|
||||
_title: 'Test querystring'
|
||||
_controller: '\Drupal\common_test\Controller\CommonTestController::jsAndCssQuerystring'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\common_test\Controller\CommonTestController.
|
||||
*/
|
||||
|
||||
namespace Drupal\common_test\Controller;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Controller routines for common_test routes.
|
||||
*/
|
||||
class CommonTestController {
|
||||
|
||||
/**
|
||||
* Returns links to the current page, with and without query strings.
|
||||
*
|
||||
* Using #type 'link' causes these links to be rendered with _l().
|
||||
*/
|
||||
public function typeLinkActiveClass() {
|
||||
return array(
|
||||
'no_query' => array(
|
||||
'#type' => 'link',
|
||||
'#title' => t('Link with no query string'),
|
||||
'#url' => Url::fromRoute('<current>'),
|
||||
'#options' => array(
|
||||
'set_active_class' => TRUE,
|
||||
),
|
||||
),
|
||||
'with_query' => array(
|
||||
'#type' => 'link',
|
||||
'#title' => t('Link with a query string'),
|
||||
'#url' => Url::fromRoute('<current>'),
|
||||
'#options' => array(
|
||||
'query' => array(
|
||||
'foo' => 'bar',
|
||||
'one' => 'two',
|
||||
),
|
||||
'set_active_class' => TRUE,
|
||||
),
|
||||
),
|
||||
'with_query_reversed' => array(
|
||||
'#type' => 'link',
|
||||
'#title' => t('Link with the same query string in reverse order'),
|
||||
'#url' => Url::fromRoute('<current>'),
|
||||
'#options' => array(
|
||||
'query' => array(
|
||||
'one' => 'two',
|
||||
'foo' => 'bar',
|
||||
),
|
||||
'set_active_class' => TRUE,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a JavaScript file and a CSS file with a query string appended.
|
||||
*
|
||||
* @return string
|
||||
* An empty string.
|
||||
*/
|
||||
public function jsAndCssQuerystring() {
|
||||
$attached = array(
|
||||
'#attached' => array(
|
||||
'library' => array(
|
||||
'node/drupal.node',
|
||||
),
|
||||
'css' => array(
|
||||
drupal_get_path('module', 'node') . '/css/node.admin.css' => array(),
|
||||
// A relative URI may have a query string.
|
||||
'/' . drupal_get_path('module', 'node') . '/node-fake.css?arg1=value1&arg2=value2' => array(),
|
||||
),
|
||||
),
|
||||
);
|
||||
return \Drupal::service('renderer')->renderRoot($attached);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a destination query parameter.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* A new Response object containing a string with the destination query
|
||||
* parameter.
|
||||
*/
|
||||
public function destination() {
|
||||
$destination = \Drupal::destination()->getAsArray();
|
||||
$output = "The destination: " . SafeMarkup::checkPlain($destination['destination']);
|
||||
return new Response($output);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{#
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation for the common test foo.
|
||||
*
|
||||
* Available variables:
|
||||
* - foo: foo.
|
||||
* - bar: bar.
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
#}
|
||||
{{ foo }}{{ bar -}}
|
|
@ -0,0 +1,12 @@
|
|||
{#
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation for the common test render element.
|
||||
*
|
||||
* Available variables:
|
||||
* - foo: A render array.
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
#}
|
||||
{{ foo }}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Common Test Cron Helper'
|
||||
type: module
|
||||
description: 'Helper module for CronRunTestCase::testCronExceptions().'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Helper module for the testCronExceptions in addition to common_test module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_cron().
|
||||
*
|
||||
* common_test_cron() throws an exception, but the execution should reach this
|
||||
* function as well.
|
||||
*
|
||||
* @see common_test_cron()
|
||||
*/
|
||||
function common_test_cron_helper_cron() {
|
||||
\Drupal::state()->set('common_test.cron', 'success');
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: "Condition Test Support"
|
||||
type: module
|
||||
description: "Test general form component for condition plugins."
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,6 @@
|
|||
condition_test.1:
|
||||
path: '/condition_test'
|
||||
defaults:
|
||||
_form: '\Drupal\condition_test\FormController'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\condition_test\FormController.
|
||||
*/
|
||||
|
||||
namespace Drupal\condition_test;
|
||||
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Condition\ConditionManager;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Routing controller class for condition_test testing of condition forms.
|
||||
*/
|
||||
class FormController implements FormInterface {
|
||||
|
||||
/**
|
||||
* The condition plugin we will be working with.
|
||||
*
|
||||
* @var \Drupal\Core\Condition\ConditionInterface
|
||||
*/
|
||||
protected $condition;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'condition_node_type_test_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a \Drupal\condition_test\FormController object.
|
||||
*/
|
||||
public function __construct() {
|
||||
$manager = new ConditionManager(\Drupal::service('container.namespaces'), \Drupal::cache('discovery'), \Drupal::moduleHandler());
|
||||
$this->condition = $manager->createInstance('node_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form = $this->condition->buildConfigurationForm($form, $form_state);
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Submit'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\Form\FormInterface::validateForm().
|
||||
*
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->condition->validateConfigurationForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->condition->submitConfigurationForm($form, $form_state);
|
||||
$config = $this->condition->getConfig();
|
||||
foreach ($config['bundles'] as $bundle) {
|
||||
drupal_set_message('Bundle: ' . $bundle);
|
||||
}
|
||||
|
||||
$article = Node::load(1);
|
||||
$this->condition->setContextValue('node', $article);
|
||||
if ($this->condition->execute()) {
|
||||
drupal_set_message(t('Executed successfully.'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\condition_test\Plugin\Condition\ConditionTestDualUser.
|
||||
*/
|
||||
|
||||
namespace Drupal\condition_test\Plugin\Condition;
|
||||
|
||||
use Drupal\Core\Condition\ConditionPluginBase;
|
||||
|
||||
/**
|
||||
* Provides a condition that requires two users.
|
||||
*
|
||||
* @Condition(
|
||||
* id = "condition_test_dual_user",
|
||||
* label = @Translation("Dual user"),
|
||||
* context = {
|
||||
* "user1" = @ContextDefinition("entity:user", label = @Translation("User 1")),
|
||||
* "user2" = @ContextDefinition("entity:user", label = @Translation("User 2"))
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class ConditionTestDualUser extends ConditionPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function evaluate() {
|
||||
$user1 = $this->getContextValue('user1');
|
||||
$user2 = $this->getContextValue('user2');
|
||||
return $user1->id() === $user2->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
return $this->t('This condition has two users.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\condition_test\Tests\ConditionTestDualUserTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\condition_test\Tests;
|
||||
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests a condition that requires two users.
|
||||
*
|
||||
* @group condition_test
|
||||
*/
|
||||
class ConditionTestDualUserTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* An anonymous user for testing purposes.
|
||||
*
|
||||
* @var \Drupal\user\Entity\User
|
||||
*/
|
||||
protected $anonymous;
|
||||
|
||||
/**
|
||||
* An authenticated user for testing purposes.
|
||||
*
|
||||
* @var \Drupal\user\Entity\User
|
||||
*/
|
||||
protected $authenticated;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'user', 'condition_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installSchema('system', 'sequences');
|
||||
$this->installEntitySchema('user');
|
||||
|
||||
$this->anonymous = User::create(['uid' => 0]);
|
||||
$this->authenticated = User::create(['uid' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the dual user condition.
|
||||
*/
|
||||
public function testConditions() {
|
||||
$this->doTestIdenticalUser();
|
||||
$this->doTestDifferentUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with both contexts mapped to the same user.
|
||||
*/
|
||||
protected function doTestIdenticalUser() {
|
||||
/** @var \Drupal\Core\Condition\ConditionPluginBase $condition */
|
||||
$condition = \Drupal::service('plugin.manager.condition')
|
||||
->createInstance('condition_test_dual_user')
|
||||
// Map the anonymous user to both contexts.
|
||||
->setContextMapping([
|
||||
'user1' => 'anonymous',
|
||||
'user2' => 'anonymous',
|
||||
]);
|
||||
$definition = new ContextDefinition('entity:user');
|
||||
$contexts['anonymous'] = (new Context($definition))->setContextValue($this->anonymous);
|
||||
\Drupal::service('context.handler')->applyContextMapping($condition, $contexts);
|
||||
$this->assertTrue($condition->execute());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with each context mapped to different users.
|
||||
*/
|
||||
protected function doTestDifferentUser() {
|
||||
/** @var \Drupal\Core\Condition\ConditionPluginBase $condition */
|
||||
$condition = \Drupal::service('plugin.manager.condition')
|
||||
->createInstance('condition_test_dual_user')
|
||||
->setContextMapping([
|
||||
'user1' => 'anonymous',
|
||||
'user2' => 'authenticated',
|
||||
]);
|
||||
$definition = new ContextDefinition('entity:user');
|
||||
$contexts['anonymous'] = (new Context($definition))->setContextValue($this->anonymous);
|
||||
$contexts['authenticated'] = (new Context($definition))->setContextValue($this->authenticated);
|
||||
\Drupal::service('context.handler')->applyContextMapping($condition, $contexts);
|
||||
$this->assertFalse($condition->execute());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: Content negotiation test
|
||||
type: module
|
||||
description: 'Support testing content negotiation variations.'
|
||||
package: Core
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,32 @@
|
|||
# Tests
|
||||
conneg.simpletest:
|
||||
path: conneg/simple.json
|
||||
defaults:
|
||||
_controller: '\Drupal\conneg_test\Controller\TestController::simple'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
conneg.html:
|
||||
path: conneg/html
|
||||
defaults:
|
||||
_controller: '\Drupal\conneg_test\Controller\TestController::html'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
conneg.simple_conneg:
|
||||
path: conneg/html
|
||||
defaults:
|
||||
_controller: '\Drupal\conneg_test\Controller\TestController::format'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
_format: 'json|xml'
|
||||
conneg.variable_with_period:
|
||||
path: conneg/plugin/{plugin_id}
|
||||
defaults:
|
||||
_controller: '\Drupal\conneg_test\Controller\TestController::variable'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
conneg.full_content_negotiation:
|
||||
path: conneg/negotiate
|
||||
defaults:
|
||||
_controller: '\Drupal\conneg_test\Controller\TestController::format'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\conneg_test\Controller\TestController.
|
||||
*/
|
||||
|
||||
namespace Drupal\conneg_test\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Test controller for content negotation tests.
|
||||
*/
|
||||
class TestController {
|
||||
|
||||
/**
|
||||
* Returns a json response.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function simple() {
|
||||
return new JsonResponse(['some' => 'data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a simple render array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function html() {
|
||||
return [
|
||||
'#markup' => 'here',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns different responses dependening on the request format.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* The response.
|
||||
*/
|
||||
public function format(Request $request) {
|
||||
switch ($request->getRequestFormat()) {
|
||||
case 'json':
|
||||
return new JsonResponse(['some' => 'data']);
|
||||
|
||||
case 'xml':
|
||||
return new Response('<xml></xml>', Response::HTTP_OK, ['Content-Type' => 'application/xml']);
|
||||
|
||||
default:
|
||||
return new Response($request->getRequestFormat());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a render array depending on some passed in value.
|
||||
*
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
*
|
||||
* @return array
|
||||
* The render array
|
||||
*/
|
||||
public function variable($plugin_id) {
|
||||
return [
|
||||
'#markup' => $plugin_id,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Cron Queue test'
|
||||
type: module
|
||||
description: 'Support module for the cron queue runner.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\cron_queue_test\Plugin\QueueWorker\CronQueueTestBrokenQueue.
|
||||
*/
|
||||
|
||||
namespace Drupal\cron_queue_test\Plugin\QueueWorker;
|
||||
|
||||
use Drupal\Core\Queue\QueueWorkerBase;
|
||||
use Drupal\Core\Queue\SuspendQueueException;
|
||||
|
||||
/**
|
||||
* @QueueWorker(
|
||||
* id = "cron_queue_test_broken_queue",
|
||||
* title = @Translation("Broken queue test"),
|
||||
* cron = {"time" = 60}
|
||||
* )
|
||||
*/
|
||||
class CronQueueTestBrokenQueue extends QueueWorkerBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processItem($data) {
|
||||
if ($data == 'crash') {
|
||||
throw new SuspendQueueException('The queue is broken.');
|
||||
}
|
||||
// Do nothing otherwise.
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\cron_queue_test\Plugin\QueueWorker\CronQueueTestException.
|
||||
*/
|
||||
|
||||
namespace Drupal\cron_queue_test\Plugin\QueueWorker;
|
||||
|
||||
use Drupal\Core\Queue\QueueWorkerBase;
|
||||
|
||||
/**
|
||||
* @QueueWorker(
|
||||
* id = "cron_queue_test_exception",
|
||||
* title = @Translation("Exception test"),
|
||||
* cron = {"time" = 60}
|
||||
* )
|
||||
*/
|
||||
class CronQueueTestException extends QueueWorkerBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processItem($data) {
|
||||
throw new \Exception('That is not supposed to happen.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Database Test'
|
||||
type: module
|
||||
description: 'Support module for Database layer tests.'
|
||||
core: 8.x
|
||||
package: Testing
|
||||
version: VERSION
|
|
@ -0,0 +1,278 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the database_test module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*
|
||||
* The database tests use the database API which depends on schema
|
||||
* information for certain operations on certain databases.
|
||||
* Therefore, the schema must actually be declared in a normal module
|
||||
* like any other, not directly in the test file.
|
||||
*/
|
||||
function database_test_schema() {
|
||||
$schema['test'] = array(
|
||||
'description' => 'Basic test table for the database unit tests.',
|
||||
'fields' => array(
|
||||
'id' => array(
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => "A person's name",
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'binary' => TRUE,
|
||||
),
|
||||
'age' => array(
|
||||
'description' => "The person's age",
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'job' => array(
|
||||
'description' => "The person's job",
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => 'Undefined',
|
||||
),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
'unique keys' => array(
|
||||
'name' => array('name')
|
||||
),
|
||||
'indexes' => array(
|
||||
'ages' => array('age'),
|
||||
),
|
||||
);
|
||||
|
||||
// This is an alternate version of the same table that is structured the same
|
||||
// but has a non-serial Primary Key.
|
||||
$schema['test_people'] = array(
|
||||
'description' => 'A duplicate version of the test table, used for additional tests.',
|
||||
'fields' => array(
|
||||
'name' => array(
|
||||
'description' => "A person's name",
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'age' => array(
|
||||
'description' => "The person's age",
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'job' => array(
|
||||
'description' => "The person's job",
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
),
|
||||
'primary key' => array('job'),
|
||||
'indexes' => array(
|
||||
'ages' => array('age'),
|
||||
),
|
||||
);
|
||||
|
||||
$schema['test_people_copy'] = array(
|
||||
'description' => 'A duplicate version of the test_people table, used for additional tests.',
|
||||
'fields' => array(
|
||||
'name' => array(
|
||||
'description' => "A person's name",
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'age' => array(
|
||||
'description' => "The person's age",
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'job' => array(
|
||||
'description' => "The person's job",
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
),
|
||||
'primary key' => array('job'),
|
||||
'indexes' => array(
|
||||
'ages' => array('age'),
|
||||
),
|
||||
);
|
||||
|
||||
$schema['test_one_blob'] = array(
|
||||
'description' => 'A simple table including a BLOB field for testing BLOB behavior.',
|
||||
'fields' => array(
|
||||
'id' => array(
|
||||
'description' => 'Simple unique ID.',
|
||||
'type' => 'serial',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'blob1' => array(
|
||||
'description' => 'A BLOB field.',
|
||||
'type' => 'blob',
|
||||
),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
);
|
||||
|
||||
$schema['test_two_blobs'] = array(
|
||||
'description' => 'A simple test table with two BLOB fields.',
|
||||
'fields' => array(
|
||||
'id' => array(
|
||||
'description' => 'Simple unique ID.',
|
||||
'type' => 'serial',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'blob1' => array(
|
||||
'description' => 'A dummy BLOB field.',
|
||||
'type' => 'blob',
|
||||
),
|
||||
'blob2' => array(
|
||||
'description' => 'A second BLOB field.',
|
||||
'type' => 'blob'
|
||||
),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
);
|
||||
|
||||
$schema['test_task'] = array(
|
||||
'description' => 'A task list for people in the test table.',
|
||||
'fields' => array(
|
||||
'tid' => array(
|
||||
'description' => 'Task ID, primary key.',
|
||||
'type' => 'serial',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'pid' => array(
|
||||
'description' => 'The {test_people}.pid, foreign key for the test table.',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'task' => array(
|
||||
'description' => 'The task to be completed.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'priority' => array(
|
||||
'description' => 'The priority of the task.',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
),
|
||||
'primary key' => array('tid'),
|
||||
);
|
||||
|
||||
$schema['test_null'] = array(
|
||||
'description' => 'Basic test table for NULL value handling.',
|
||||
'fields' => array(
|
||||
'id' => array(
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => "A person's name.",
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
'default' => '',
|
||||
),
|
||||
'age' => array(
|
||||
'description' => "The person's age.",
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => FALSE,
|
||||
'default' => 0),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
'unique keys' => array(
|
||||
'name' => array('name')
|
||||
),
|
||||
'indexes' => array(
|
||||
'ages' => array('age'),
|
||||
),
|
||||
);
|
||||
|
||||
$schema['test_serialized'] = array(
|
||||
'description' => 'Basic test table for NULL value handling.',
|
||||
'fields' => array(
|
||||
'id' => array(
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => "A person's name.",
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
'default' => '',
|
||||
),
|
||||
'info' => array(
|
||||
'description' => "The person's data in serialized form.",
|
||||
'type' => 'blob',
|
||||
'serialize' => TRUE,
|
||||
),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
'unique keys' => array(
|
||||
'name' => array('name')
|
||||
),
|
||||
);
|
||||
|
||||
$schema['test_composite_primary'] = array(
|
||||
'description' => 'Basic test table with a composite primary key',
|
||||
'fields' => array(
|
||||
'name' => array(
|
||||
'description' => "A person's name",
|
||||
'type' => 'varchar',
|
||||
'length' => 50,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'binary' => TRUE,
|
||||
),
|
||||
'age' => array(
|
||||
'description' => "The person's age",
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'job' => array(
|
||||
'description' => "The person's job",
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => 'Undefined',
|
||||
),
|
||||
),
|
||||
'primary key' => array('name', 'age'),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
use Drupal\Core\Database\Query\AlterableInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
/**
|
||||
* Implements hook_query_alter().
|
||||
*/
|
||||
function database_test_query_alter(AlterableInterface $query) {
|
||||
|
||||
if ($query->hasTag('database_test_alter_add_range')) {
|
||||
$query->range(0, 2);
|
||||
}
|
||||
|
||||
if ($query->hasTag('database_test_alter_add_join')) {
|
||||
$people_alias = $query->join('test', 'people', "test_task.pid = %alias.id");
|
||||
$query->addField($people_alias, 'name', 'name');
|
||||
$query->condition($people_alias . '.id', 2);
|
||||
}
|
||||
|
||||
if ($query->hasTag('database_test_alter_change_conditional')) {
|
||||
$conditions =& $query->conditions();
|
||||
$conditions[0]['value'] = 2;
|
||||
}
|
||||
|
||||
if ($query->hasTag('database_test_alter_change_fields')) {
|
||||
$fields =& $query->getFields();
|
||||
unset($fields['age']);
|
||||
}
|
||||
|
||||
if ($query->hasTag('database_test_alter_change_expressions')) {
|
||||
$expressions =& $query->getExpressions();
|
||||
$expressions['double_age']['expression'] = 'age*3';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements hook_query_TAG_alter().
|
||||
*
|
||||
* Called by DatabaseTestCase::testAlterRemoveRange.
|
||||
*/
|
||||
function database_test_query_database_test_alter_remove_range_alter(AlterableInterface $query) {
|
||||
$query->range();
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
database_test.db_query_temporary:
|
||||
path: '/database_test/db_query_temporary'
|
||||
defaults:
|
||||
_controller: '\Drupal\database_test\Controller\DatabaseTestController::dbQueryTemporary'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
database_test.pager_query_even:
|
||||
path: '/database_test/pager_query_even/{limit}'
|
||||
defaults:
|
||||
_controller: '\Drupal\database_test\Controller\DatabaseTestController::pagerQueryEven'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
database_test.pager_query_odd:
|
||||
path: '/database_test/pager_query_odd/{limit}'
|
||||
defaults:
|
||||
_controller: '\Drupal\database_test\Controller\DatabaseTestController::pagerQueryOdd'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
database_test.tablesort:
|
||||
path: '/database_test/tablesort'
|
||||
defaults:
|
||||
_controller: '\Drupal\database_test\Controller\DatabaseTestController::testTablesort'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
database_test.tablesort_first:
|
||||
path: '/database_test/tablesort_first'
|
||||
defaults:
|
||||
_controller: '\Drupal\database_test\Controller\DatabaseTestController::testTablesortFirst'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
database_test.tablesort_default_sort:
|
||||
path: '/database_test/tablesort_default_sort'
|
||||
defaults:
|
||||
_form: '\Drupal\database_test\Form\DatabaseTestForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\database_test\Controller\DatabaseTestController.
|
||||
*/
|
||||
|
||||
namespace Drupal\database_test\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
/**
|
||||
* Controller routines for database_test routes.
|
||||
*/
|
||||
class DatabaseTestController {
|
||||
|
||||
/**
|
||||
* Runs db_query_temporary() and outputs the table name and its number of rows.
|
||||
*
|
||||
* We need to test that the table created is temporary, so we run it here, in a
|
||||
* separate menu callback request; After this request is done, the temporary
|
||||
* table should automatically dropped.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function dbQueryTemporary() {
|
||||
$table_name = db_query_temporary('SELECT age FROM {test}', array());
|
||||
return new JsonResponse(array(
|
||||
'table_name' => $table_name,
|
||||
'row_count' => db_select($table_name)->countQuery()->execute()->fetchField(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a pager query and returns the results.
|
||||
*
|
||||
* This function does care about the page GET parameter, as set by the
|
||||
* simpletest HTTP call.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function pagerQueryEven($limit) {
|
||||
$query = db_select('test', 't');
|
||||
$query
|
||||
->fields('t', array('name'))
|
||||
->orderBy('age');
|
||||
|
||||
// This should result in 2 pages of results.
|
||||
$query = $query
|
||||
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
|
||||
->limit($limit);
|
||||
|
||||
$names = $query->execute()->fetchCol();
|
||||
|
||||
return new JsonResponse(array(
|
||||
'names' => $names,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a pager query and returns the results.
|
||||
*
|
||||
* This function does care about the page GET parameter, as set by the
|
||||
* simpletest HTTP call.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function pagerQueryOdd($limit) {
|
||||
$query = db_select('test_task', 't');
|
||||
$query
|
||||
->fields('t', array('task'))
|
||||
->orderBy('pid');
|
||||
|
||||
// This should result in 4 pages of results.
|
||||
$query = $query
|
||||
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
|
||||
->limit($limit);
|
||||
|
||||
$names = $query->execute()->fetchCol();
|
||||
|
||||
return new JsonResponse(array(
|
||||
'names' => $names,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a tablesort query and returns the results.
|
||||
*
|
||||
* This function does care about the page GET parameter, as set by the
|
||||
* simpletest HTTP call.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function testTablesort() {
|
||||
$header = array(
|
||||
'tid' => array('data' => t('Task ID'), 'field' => 'tid', 'sort' => 'desc'),
|
||||
'pid' => array('data' => t('Person ID'), 'field' => 'pid'),
|
||||
'task' => array('data' => t('Task'), 'field' => 'task'),
|
||||
'priority' => array('data' => t('Priority'), 'field' => 'priority', ),
|
||||
);
|
||||
|
||||
$query = db_select('test_task', 't');
|
||||
$query
|
||||
->fields('t', array('tid', 'pid', 'task', 'priority'));
|
||||
|
||||
$query = $query
|
||||
->extend('Drupal\Core\Database\Query\TableSortExtender')
|
||||
->orderByHeader($header);
|
||||
|
||||
// We need all the results at once to check the sort.
|
||||
$tasks = $query->execute()->fetchAll();
|
||||
|
||||
return new JsonResponse(array(
|
||||
'tasks' => $tasks,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a tablesort query with a second order_by after and returns the results.
|
||||
*
|
||||
* This function does care about the page GET parameter, as set by the
|
||||
* simpletest HTTP call.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function testTablesortFirst() {
|
||||
$header = array(
|
||||
'tid' => array('data' => t('Task ID'), 'field' => 'tid', 'sort' => 'desc'),
|
||||
'pid' => array('data' => t('Person ID'), 'field' => 'pid'),
|
||||
'task' => array('data' => t('Task'), 'field' => 'task'),
|
||||
'priority' => array('data' => t('Priority'), 'field' => 'priority', ),
|
||||
);
|
||||
|
||||
$query = db_select('test_task', 't');
|
||||
$query
|
||||
->fields('t', array('tid', 'pid', 'task', 'priority'));
|
||||
|
||||
$query = $query
|
||||
->extend('Drupal\Core\Database\Query\TableSortExtender')
|
||||
->orderByHeader($header)
|
||||
->orderBy('priority');
|
||||
|
||||
// We need all the results at once to check the sort.
|
||||
$tasks = $query->execute()->fetchAll();
|
||||
|
||||
return new JsonResponse(array(
|
||||
'tasks' => $tasks,
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\database_test\Form\DatabaseTestForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\database_test\Form;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Form controller for database_test module.
|
||||
*/
|
||||
class DatabaseTestForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'database_test_theme_tablesort';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$header = array(
|
||||
'username' => array('data' => t('Username'), 'field' => 'u.name'),
|
||||
'status' => array('data' => t('Status'), 'field' => 'u.status'),
|
||||
);
|
||||
|
||||
$query = db_select('users_field_data', 'u');
|
||||
$query->condition('u.uid', 0, '<>');
|
||||
$query->condition('u.default_langcode', 1);
|
||||
|
||||
$count_query = clone $query;
|
||||
$count_query->addExpression('COUNT(u.uid)');
|
||||
|
||||
$query = $query
|
||||
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
|
||||
->extend('Drupal\Core\Database\Query\TableSortExtender');
|
||||
$query
|
||||
->fields('u', array('uid'))
|
||||
->limit(50)
|
||||
->orderByHeader($header)
|
||||
->setCountQuery($count_query);
|
||||
$uids = $query
|
||||
->execute()
|
||||
->fetchCol();
|
||||
|
||||
$options = array();
|
||||
|
||||
foreach (User::loadMultiple($uids) as $account) {
|
||||
$options[$account->id()] = array(
|
||||
'title' => array('data' => array('#title' => SafeMarkup::checkPlain($account->getUsername()))),
|
||||
'username' => SafeMarkup::checkPlain($account->getUsername()),
|
||||
'status' => $account->isActive() ? t('active') : t('blocked'),
|
||||
);
|
||||
}
|
||||
|
||||
$form['accounts'] = array(
|
||||
'#type' => 'tableselect',
|
||||
'#header' => $header,
|
||||
'#options' => $options,
|
||||
'#empty' => t('No people available.'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Drupal system listing compatible test'
|
||||
type: module
|
||||
description: 'Support module for testing the drupal_system_listing function.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Entity CRUD Hooks Test'
|
||||
type: module
|
||||
description: 'Support module for CRUD hook tests.'
|
||||
core: 8.x
|
||||
package: Testing
|
||||
version: VERSION
|
|
@ -0,0 +1,400 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test module for the Entity CRUD API.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_create().
|
||||
*/
|
||||
function entity_crud_hook_test_entity_create(EntityInterface $entity) {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create() for block entities.
|
||||
*/
|
||||
function entity_crud_hook_test_block_create() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create() for comment entities.
|
||||
*/
|
||||
function entity_crud_hook_test_comment_create() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create() for file entities.
|
||||
*/
|
||||
function entity_crud_hook_test_file_create() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create() for node entities.
|
||||
*/
|
||||
function entity_crud_hook_test_node_create() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create() for taxonomy_term entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_term_create() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create() for taxonomy_vocabulary entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_vocabulary_create() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create() for user entities.
|
||||
*/
|
||||
function entity_crud_hook_test_user_create() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_presave().
|
||||
*/
|
||||
function entity_crud_hook_test_entity_presave(EntityInterface $entity) {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave() for block entities.
|
||||
*/
|
||||
function entity_crud_hook_test_block_presave() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave() for comment entities.
|
||||
*/
|
||||
function entity_crud_hook_test_comment_presave() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave() for file entities.
|
||||
*/
|
||||
function entity_crud_hook_test_file_presave() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave() for node entities.
|
||||
*/
|
||||
function entity_crud_hook_test_node_presave() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave() for taxonomy_term entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_term_presave() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave() for taxonomy_vocabulary entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_vocabulary_presave() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave() for user entities.
|
||||
*/
|
||||
function entity_crud_hook_test_user_presave() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_insert().
|
||||
*/
|
||||
function entity_crud_hook_test_entity_insert(EntityInterface $entity) {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for block entities.
|
||||
*/
|
||||
function entity_crud_hook_test_block_insert() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for comment entities.
|
||||
*/
|
||||
function entity_crud_hook_test_comment_insert() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for file entities.
|
||||
*/
|
||||
function entity_crud_hook_test_file_insert() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for node entities.
|
||||
*/
|
||||
function entity_crud_hook_test_node_insert() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for taxonomy_term entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_term_insert() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for taxonomy_vocabulary entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_vocabulary_insert() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for user entities.
|
||||
*/
|
||||
function entity_crud_hook_test_user_insert() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_load().
|
||||
*/
|
||||
function entity_crud_hook_test_entity_load(array $entities, $type) {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for block entities.
|
||||
*/
|
||||
function entity_crud_hook_test_block_load() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for comment entities.
|
||||
*/
|
||||
function entity_crud_hook_test_comment_load() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for file entities.
|
||||
*/
|
||||
function entity_crud_hook_test_file_load() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for node entities.
|
||||
*/
|
||||
function entity_crud_hook_test_node_load() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for taxonomy_term entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_term_load() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for taxonomy_vocabulary entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_vocabulary_load() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for user entities.
|
||||
*/
|
||||
function entity_crud_hook_test_user_load() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_update().
|
||||
*/
|
||||
function entity_crud_hook_test_entity_update(EntityInterface $entity) {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update() for block entities.
|
||||
*/
|
||||
function entity_crud_hook_test_block_update() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update() for comment entities.
|
||||
*/
|
||||
function entity_crud_hook_test_comment_update() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update() for file entities.
|
||||
*/
|
||||
function entity_crud_hook_test_file_update() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update() for node entities.
|
||||
*/
|
||||
function entity_crud_hook_test_node_update() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update() for taxonomy_term entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_term_update() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update() for taxonomy_vocabulary entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_vocabulary_update() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update() for user entities.
|
||||
*/
|
||||
function entity_crud_hook_test_user_update() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_predelete().
|
||||
*/
|
||||
function entity_crud_hook_test_entity_predelete(EntityInterface $entity) {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_predelete() for block entities.
|
||||
*/
|
||||
function entity_crud_hook_test_block_predelete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_predelete() for comment entities.
|
||||
*/
|
||||
function entity_crud_hook_test_comment_predelete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_predelete() for file entities.
|
||||
*/
|
||||
function entity_crud_hook_test_file_predelete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_predelete() for node entities.
|
||||
*/
|
||||
function entity_crud_hook_test_node_predelete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_predelete() for taxonomy_term entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_term_predelete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_predelete() for taxonomy_vocabulary entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_vocabulary_predelete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_predelete() for user entities.
|
||||
*/
|
||||
function entity_crud_hook_test_user_predelete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_delete().
|
||||
*/
|
||||
function entity_crud_hook_test_entity_delete(EntityInterface $entity) {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete() for block entities.
|
||||
*/
|
||||
function entity_crud_hook_test_block_delete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete() for comment entities.
|
||||
*/
|
||||
function entity_crud_hook_test_comment_delete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete() for file entities.
|
||||
*/
|
||||
function entity_crud_hook_test_file_delete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete() for node entities.
|
||||
*/
|
||||
function entity_crud_hook_test_node_delete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete() for taxonomy_term entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_term_delete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete() for taxonomy_vocabulary entities.
|
||||
*/
|
||||
function entity_crud_hook_test_taxonomy_vocabulary_delete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_delete() for user entities.
|
||||
*/
|
||||
function entity_crud_hook_test_user_delete() {
|
||||
$GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
name: 'Entity schema test module'
|
||||
type: module
|
||||
description: 'Provides entity and field definitions to test entity schema.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- entity_test
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test module for the entity API providing a bundle field.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\entity_test\FieldStorageDefinition;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_type_alter().
|
||||
*/
|
||||
function entity_schema_test_entity_type_alter(array &$entity_types) {
|
||||
if (\Drupal::state()->get('entity_schema_update')) {
|
||||
$entity_type = $entity_types['entity_test'];
|
||||
$entity_type->set('translatable', TRUE);
|
||||
$entity_type->set('data_table', 'entity_test_field_data');
|
||||
$keys = $entity_type->getKeys();
|
||||
$keys['revision'] = 'revision_id';
|
||||
$entity_type->set('entity_keys', $keys);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_base_field_info().
|
||||
*/
|
||||
function entity_schema_test_entity_base_field_info(EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->id() == 'entity_test') {
|
||||
$definitions['custom_base_field'] = BaseFieldDefinition::create('string')
|
||||
->setName('custom_base_field')
|
||||
->setLabel(t('A custom base field'));
|
||||
if (\Drupal::state()->get('entity_schema_update')) {
|
||||
$definitions += EntityTestMulRev::baseFieldDefinitions($entity_type);
|
||||
// And add a revision log.
|
||||
$definitions['revision_log'] = BaseFieldDefinition::create('string_long')
|
||||
->setLabel(t('Revision log message'))
|
||||
->setDescription(t('The log entry explaining the changes in this revision.'))
|
||||
->setRevisionable(TRUE);
|
||||
}
|
||||
return $definitions;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_field_storage_info().
|
||||
*/
|
||||
function entity_schema_test_entity_field_storage_info(EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->id() == 'entity_test') {
|
||||
$definitions['custom_bundle_field'] = FieldStorageDefinition::create('string')
|
||||
->setName('custom_bundle_field')
|
||||
->setLabel(t('A custom bundle field'))
|
||||
->setTargetEntityTypeId($entity_type->id());
|
||||
return $definitions;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_bundle_field_info().
|
||||
*/
|
||||
function entity_schema_test_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle) {
|
||||
if ($entity_type->id() == 'entity_test' && $bundle == 'custom') {
|
||||
$definitions['custom_bundle_field'] = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type->id())['custom_bundle_field'];
|
||||
return $definitions;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_bundle_create().
|
||||
*/
|
||||
function entity_schema_test_entity_bundle_create($entity_type_id, $bundle) {
|
||||
if ($entity_type_id == 'entity_test' && $bundle == 'custom') {
|
||||
$entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
|
||||
$field_definitions = entity_schema_test_entity_bundle_field_info($entity_type, $bundle);
|
||||
$field_definitions['custom_bundle_field']
|
||||
->setTargetEntityTypeId($entity_type_id)
|
||||
->setTargetBundle($bundle);
|
||||
// Notify the entity storage that we just created a new field.
|
||||
\Drupal::entityManager()->onFieldDefinitionCreate($field_definitions['custom_bundle_field']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_bundle_delete().
|
||||
*/
|
||||
function entity_schema_test_entity_bundle_delete($entity_type_id, $bundle) {
|
||||
if ($entity_type_id == 'entity_test' && $bundle == 'custom') {
|
||||
$entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
|
||||
$field_definitions = entity_schema_test_entity_bundle_field_info($entity_type, $bundle);
|
||||
$field_definitions['custom_bundle_field']
|
||||
->setTargetEntityTypeId($entity_type_id)
|
||||
->setTargetBundle($bundle);
|
||||
// Notify the entity storage that our field is gone.
|
||||
\Drupal::entityManager()->onFieldDefinitionDelete($field_definitions['custom_bundle_field']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
id: entity_test.full
|
||||
label: Full
|
||||
status: false
|
||||
cache: true
|
||||
targetEntityType: entity_test
|
||||
dependencies:
|
||||
module:
|
||||
- entity_test
|
|
@ -0,0 +1,8 @@
|
|||
id: entity_test.test
|
||||
label: Test
|
||||
status: false
|
||||
cache: false
|
||||
targetEntityType: entity_test
|
||||
dependencies:
|
||||
module:
|
||||
- entity_test
|
|
@ -0,0 +1,15 @@
|
|||
core.entity_view_display.*.*.*.third_party.entity_test:
|
||||
type: mapping
|
||||
label: 'Schema for entity_test module additions to entity_view_display entity'
|
||||
mapping:
|
||||
foo:
|
||||
type: string
|
||||
label: 'Label for foo'
|
||||
|
||||
field.storage_settings.shape:
|
||||
type: mapping
|
||||
label: 'Shape field storage settings'
|
||||
mapping:
|
||||
foreign_key_name:
|
||||
type: string
|
||||
label: 'Foreign key name'
|
|
@ -0,0 +1,10 @@
|
|||
name: 'Entity CRUD test module'
|
||||
type: module
|
||||
description: 'Provides entity types based upon the CRUD API.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- field
|
||||
- text
|
||||
- entity_reference
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the entity_test module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function entity_test_install() {
|
||||
foreach (entity_test_entity_types() as $entity_type) {
|
||||
// Auto-create fields for testing.
|
||||
entity_create('field_storage_config', array(
|
||||
'entity_type' => $entity_type,
|
||||
'field_name' => 'field_test_text',
|
||||
'type' => 'text',
|
||||
'cardinality' => 1,
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'entity_type' => $entity_type,
|
||||
'field_name' => 'field_test_text',
|
||||
'bundle' => $entity_type,
|
||||
'label' => 'Test text-field',
|
||||
'translatable' => FALSE,
|
||||
))->save();
|
||||
|
||||
entity_get_form_display($entity_type, $entity_type, 'default')
|
||||
->setComponent('field_test_text', array('type' => 'text_textfield'))
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function entity_test_schema() {
|
||||
// Schema for simple entity.
|
||||
$schema['entity_test_example'] = array(
|
||||
'description' => 'Stores entity_test items.',
|
||||
'fields' => array(
|
||||
'id' => array(
|
||||
'type' => 'serial',
|
||||
'not null' => TRUE,
|
||||
'description' => 'Primary Key: Unique entity-test item ID.',
|
||||
),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
);
|
||||
return $schema;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
entity_test.local_tasks:
|
||||
deriver: 'Drupal\entity_test\Plugin\Derivative\EntityTestLocalTasks'
|
627
core/modules/system/tests/modules/entity_test/entity_test.module
Normal file
627
core/modules/system/tests/modules/entity_test/entity_test.module
Normal file
|
@ -0,0 +1,627 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test module for the entity API providing several entity types for testing.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Filter that limits test entity list to revisable ones.
|
||||
*/
|
||||
const ENTITY_TEST_TYPES_REVISABLE = 1;
|
||||
|
||||
/**
|
||||
* Filter that limits test entity list to multilingual ones.
|
||||
*/
|
||||
const ENTITY_TEST_TYPES_MULTILINGUAL = 2;
|
||||
|
||||
/**
|
||||
* Filter that limits test entity list to routeable ones.
|
||||
*/
|
||||
const ENTITY_TEST_TYPES_ROUTING = 3;
|
||||
|
||||
/**
|
||||
* Returns a list of test entity types.
|
||||
*
|
||||
* The returned entity types are one for each available entity storage type:
|
||||
* - The plain entity_test type supports neither revisions nor multilingual
|
||||
* properties.
|
||||
* - The entity_test_mul type supports multilingual properties.
|
||||
* - The entity_test_rev type supports revisions.
|
||||
* - The entity_test_mulrev type supports both revisions and multilingual
|
||||
* properties.
|
||||
*
|
||||
* @param int $filter
|
||||
* Either ENTITY_TEST_TYPES_REVISABLE to only return revisable entity types or
|
||||
* ENTITY_TEST_TYPES_MULTILINGUAL to only return multilingual ones. Defaults
|
||||
* to NULL, which returns all.
|
||||
*
|
||||
* @return array
|
||||
* List with entity_types.
|
||||
*/
|
||||
function entity_test_entity_types($filter = NULL) {
|
||||
$types = array();
|
||||
if ($filter === NULL || $filter === ENTITY_TEST_TYPES_ROUTING) {
|
||||
$types[] = 'entity_test';
|
||||
}
|
||||
if ($filter != ENTITY_TEST_TYPES_REVISABLE) {
|
||||
$types[] = 'entity_test_mul';
|
||||
$types[] = 'entity_test_mul_langcode_key';
|
||||
$types[] = 'entity_test_mul_changed';
|
||||
}
|
||||
if ($filter != ENTITY_TEST_TYPES_MULTILINGUAL) {
|
||||
$types[] = 'entity_test_rev';
|
||||
}
|
||||
if ($filter === ENTITY_TEST_TYPES_ROUTING) {
|
||||
$types[] = 'entity_test_base_field_display';
|
||||
}
|
||||
$types[] = 'entity_test_mulrev';
|
||||
$types[] = 'entity_test_mulrev_changed';
|
||||
|
||||
return array_combine($types, $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_type_alter().
|
||||
*/
|
||||
function entity_test_entity_type_alter(array &$entity_types) {
|
||||
$state = \Drupal::state();
|
||||
|
||||
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
||||
foreach (entity_test_entity_types() as $entity_type) {
|
||||
// Optionally specify a translation handler for testing translations.
|
||||
if ($state->get('entity_test.translation')) {
|
||||
$translation = $entity_types[$entity_type]->get('translation');
|
||||
$translation[$entity_type] = TRUE;
|
||||
$entity_types[$entity_type]->set('translation', $translation);
|
||||
}
|
||||
}
|
||||
|
||||
// Allow entity_test_update tests to override the entity type definition.
|
||||
$entity_types['entity_test_update'] = $state->get('entity_test_update.entity_type', $entity_types['entity_test_update']);
|
||||
|
||||
// Enable the entity_test_new only when needed.
|
||||
if (!$state->get('entity_test_new')) {
|
||||
unset($entity_types['entity_test_new']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_base_field_info_alter().
|
||||
*/
|
||||
function entity_test_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->id() == 'entity_test_mulrev' && ($names = \Drupal::state()->get('entity_test.field_definitions.translatable'))) {
|
||||
foreach ($names as $name => $value) {
|
||||
$fields[$name]->setTranslatable($value);
|
||||
}
|
||||
}
|
||||
if ($entity_type->id() == 'node' && Drupal::state()->get('entity_test.node_remove_status_field')) {
|
||||
unset($fields['status']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_field_storage_info().
|
||||
*/
|
||||
function entity_test_entity_field_storage_info(EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->id() == 'entity_test_update') {
|
||||
return \Drupal::state()->get('entity_test_update.additional_field_storage_definitions', array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bundle for entity_test entities.
|
||||
*
|
||||
* @param string $bundle
|
||||
* The machine-readable name of the bundle.
|
||||
* @param string $text
|
||||
* (optional) The human-readable name of the bundle. If none is provided, the
|
||||
* machine name will be used.
|
||||
* @param string $entity_type
|
||||
* (optional) The entity type for which the bundle is created. Defaults to
|
||||
* 'entity_test'.
|
||||
*/
|
||||
function entity_test_create_bundle($bundle, $text = NULL, $entity_type = 'entity_test') {
|
||||
$bundles = \Drupal::state()->get($entity_type . '.bundles') ?: array($entity_type => array('label' => 'Entity Test Bundle'));
|
||||
$bundles += array($bundle => array('label' => $text ? $text : $bundle));
|
||||
\Drupal::state()->set($entity_type . '.bundles', $bundles);
|
||||
|
||||
\Drupal::entityManager()->onBundleCreate($bundle, $entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a bundle for entity_test entities.
|
||||
*
|
||||
* @param string $bundle_old
|
||||
* The machine-readable name of the bundle to rename.
|
||||
* @param string $bundle_new
|
||||
* The new machine-readable name of the bundle.
|
||||
* @param string $entity_type
|
||||
* (optional) The entity type for which the bundle is renamed. Defaults to
|
||||
* 'entity_test'.
|
||||
*/
|
||||
function entity_test_rename_bundle($bundle_old, $bundle_new, $entity_type = 'entity_test') {
|
||||
$bundles = \Drupal::state()->get($entity_type . '.bundles') ?: array($entity_type => array('label' => 'Entity Test Bundle'));
|
||||
$bundles[$bundle_new] = $bundles[$bundle_old];
|
||||
unset($bundles[$bundle_old]);
|
||||
\Drupal::state()->set($entity_type . '.bundles', $bundles);
|
||||
|
||||
\Drupal::entityManager()->onBundleRename($bundle_old, $bundle_new, $entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a bundle for entity_test entities.
|
||||
*
|
||||
* @param string $bundle
|
||||
* The machine-readable name of the bundle to delete.
|
||||
* @param string $entity_type
|
||||
* (optional) The entity type for which the bundle is deleted. Defaults to
|
||||
* 'entity_test'.
|
||||
*/
|
||||
function entity_test_delete_bundle($bundle, $entity_type = 'entity_test') {
|
||||
$bundles = \Drupal::state()->get($entity_type . '.bundles') ?: array($entity_type => array('label' => 'Entity Test Bundle'));
|
||||
unset($bundles[$bundle]);
|
||||
\Drupal::state()->set($entity_type . '.bundles', $bundles);
|
||||
|
||||
\Drupal::entityManager()->onBundleDelete($bundle, $entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_bundle_info().
|
||||
*/
|
||||
function entity_test_entity_bundle_info() {
|
||||
$bundles = array();
|
||||
$entity_types = \Drupal::entityManager()->getDefinitions();
|
||||
foreach ($entity_types as $entity_type_id => $entity_type) {
|
||||
if ($entity_type->getProvider() == 'entity_test') {
|
||||
$bundles[$entity_type_id] = \Drupal::state()->get($entity_type_id . '.bundles') ?: array($entity_type_id => array('label' => 'Entity Test Bundle'));
|
||||
}
|
||||
}
|
||||
return $bundles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_view_mode_info_alter().
|
||||
*/
|
||||
function entity_test_entity_view_mode_info_alter(&$view_modes) {
|
||||
$entity_info = \Drupal::entityManager()->getDefinitions();
|
||||
foreach ($entity_info as $entity_type => $info) {
|
||||
if ($entity_info[$entity_type]->getProvider() == 'entity_test' && !isset($view_modes[$entity_type])) {
|
||||
$view_modes[$entity_type] = array(
|
||||
'full' => array(
|
||||
'label' => t('Full object'),
|
||||
'status' => TRUE,
|
||||
'cache' => TRUE,
|
||||
),
|
||||
'teaser' => array(
|
||||
'label' => t('Teaser'),
|
||||
'status' => TRUE,
|
||||
'cache' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_form_mode_info_alter().
|
||||
*/
|
||||
function entity_test_entity_form_mode_info_alter(&$form_modes) {
|
||||
$entity_info = \Drupal::entityManager()->getDefinitions();
|
||||
foreach ($entity_info as $entity_type => $info) {
|
||||
if ($entity_info[$entity_type]->getProvider() == 'entity_test') {
|
||||
$form_modes[$entity_type] = array(
|
||||
'compact' => array(
|
||||
'label' => t('Compact version'),
|
||||
'status' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_extra_field_info().
|
||||
*/
|
||||
function entity_test_entity_extra_field_info() {
|
||||
$extra['entity_test']['bundle_with_extra_fields'] = array(
|
||||
'display' => array(
|
||||
// Note: those extra fields do not currently display anything, they are
|
||||
// just used in \Drupal\field_ui\Tests\EntityDisplayTest to test the
|
||||
// behavior of entity display objects.
|
||||
'display_extra_field' => array(
|
||||
'label' => t('Display extra field'),
|
||||
'description' => t('An extra field on the display side.'),
|
||||
'weight' => 5,
|
||||
'visible' => TRUE,
|
||||
),
|
||||
'display_extra_field_hidden' => array(
|
||||
'label' => t('Display extra field (hidden)'),
|
||||
'description' => t('An extra field on the display side, hidden by default.'),
|
||||
'visible' => FALSE,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_BASE_FORM_ID_alter().
|
||||
*/
|
||||
function entity_test_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
|
||||
$langcode = $form_state->getFormObject()->getFormLangcode($form_state);
|
||||
\Drupal::state()->set('entity_test.form_langcode', $langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a test entity.
|
||||
*
|
||||
* @param int $id
|
||||
* A test entity ID.
|
||||
* @param bool $reset
|
||||
* A boolean indicating that the internal cache should be reset.
|
||||
*
|
||||
* @return \Drupal\entity_test\Entity\EntityTest
|
||||
* The loaded entity object, or NULL if the entity cannot be loaded.
|
||||
*/
|
||||
function entity_test_load($id, $reset = FALSE) {
|
||||
return entity_load('entity_test', $id, $reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a test entity.
|
||||
*
|
||||
* @param int $id
|
||||
* A test entity ID.
|
||||
* @param bool $reset
|
||||
* A boolean indicating that the internal cache should be reset.
|
||||
*
|
||||
* @return \Drupal\entity_test\Entity\EntityTestRev
|
||||
* The loaded entity object, or NULL if the entity cannot be loaded.
|
||||
*/
|
||||
function entity_test_rev_load($id, $reset = FALSE) {
|
||||
return entity_load('entity_test_rev', $id, $reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a test entity.
|
||||
*
|
||||
* @param int $id
|
||||
* A test entity ID.
|
||||
* @param bool $reset
|
||||
* A boolean indicating that the internal cache should be reset.
|
||||
*
|
||||
* @return \Drupal\entity_test\Entity\EntityTestMul
|
||||
* The loaded entity object, or FALSE if the entity cannot be loaded.
|
||||
*/
|
||||
function entity_test_mul_load($id, $reset = FALSE) {
|
||||
return entity_load('entity_test_mul', $id, $reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a test entity.
|
||||
*
|
||||
* @param int $id
|
||||
* A test entity ID.
|
||||
* @param bool $reset
|
||||
* A boolean indicating that the internal cache should be reset.
|
||||
*
|
||||
* @return \Drupal\entity_test\Entity\EntityTestMulRev
|
||||
* The loaded entity object, or NULL if the entity cannot be loaded.
|
||||
*/
|
||||
function entity_test_mulrev_load($id, $reset = FALSE) {
|
||||
return entity_load('entity_test_mulrev', $id, $reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert() for 'entity_test'.
|
||||
*/
|
||||
function entity_test_entity_test_insert($entity) {
|
||||
if ($entity->name->value == 'fail_insert') {
|
||||
throw new Exception("Test exception rollback.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_field_access().
|
||||
*
|
||||
* @see \Drupal\system\Tests\Entity\FieldAccessTest::testFieldAccess()
|
||||
*/
|
||||
function entity_test_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
|
||||
if ($field_definition->getName() == 'field_test_text') {
|
||||
if ($items) {
|
||||
if ($items->value == 'no access value') {
|
||||
return AccessResult::forbidden()->cacheUntilEntityChanges($items->getEntity());
|
||||
}
|
||||
elseif ($operation == 'edit' && $items->value == 'no edit access value') {
|
||||
return AccessResult::forbidden()->cacheUntilEntityChanges($items->getEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($field = \Drupal::state()->get('views_field_access_test-field')) {
|
||||
if ($field_definition->getName() === $field) {
|
||||
$result = AccessResult::allowedIfHasPermission($account, 'view test entity field');
|
||||
// For test purposes we want to actively deny access.
|
||||
if ($result->isNeutral()) {
|
||||
$result = AccessResult::forbidden();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_field_access_alter().
|
||||
*
|
||||
* @see \Drupal\system\Tests\Entity\FieldAccessTest::testFieldAccess()
|
||||
*/
|
||||
function entity_test_entity_field_access_alter(array &$grants, array $context) {
|
||||
if ($context['field_definition']->getName() == 'field_test_text' && $context['items']->value == 'access alter value') {
|
||||
$grants[':default'] = AccessResult::forbidden()->inheritCacheability($grants[':default'])->cacheUntilEntityChanges($context['items']->getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_form_display_alter().
|
||||
*/
|
||||
function entity_test_entity_form_display_alter(EntityFormDisplay $form_display, $context) {
|
||||
// Make the field_test_text field 42 characters for entity_test_mul.
|
||||
if ($context['entity_type'] == 'entity_test') {
|
||||
if ($component_options = $form_display->getComponent('field_test_text')) {
|
||||
$component_options['settings']['size'] = 42;
|
||||
$form_display->setComponent('field_test_text', $component_options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_presave().
|
||||
*/
|
||||
function entity_test_entity_presave(EntityInterface $entity) {
|
||||
if (isset($GLOBALS['entity_test_throw_exception'])) {
|
||||
throw new Exception('Entity presave exception', 1);
|
||||
}
|
||||
|
||||
if ($entity->getEntityType()->id() == 'entity_view_display') {
|
||||
$entity->setThirdPartySetting('entity_test', 'foo', 'bar');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_predelete().
|
||||
*/
|
||||
function entity_test_entity_predelete(EntityInterface $entity) {
|
||||
if (isset($GLOBALS['entity_test_throw_exception'])) {
|
||||
throw new Exception('Entity predelete exception', 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_operation_alter().
|
||||
*/
|
||||
function entity_test_entity_operation_alter(array &$operations, EntityInterface $entity) {
|
||||
$valid_entity_type_ids = [
|
||||
'user_role',
|
||||
'block',
|
||||
];
|
||||
if (in_array($entity->getEntityTypeId(), $valid_entity_type_ids)) {
|
||||
if (\Drupal::service('router.route_provider')->getRouteByName("entity.{$entity->getEntityTypeId()}.test_operation")) {
|
||||
$operations['test_operation'] = [
|
||||
'title' => format_string('Test Operation: @label', ['@label' => $entity->label()]),
|
||||
'url' => Url::fromRoute("entity.{$entity->getEntityTypeId()}.test_operation", [$entity->getEntityTypeId() => $entity->id()]),
|
||||
'weight' => 50,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_translation_insert().
|
||||
*/
|
||||
function entity_test_entity_translation_insert(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_translation_insert', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_translation_delete().
|
||||
*/
|
||||
function entity_test_entity_translation_delete(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_translation_delete', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mul'.
|
||||
*/
|
||||
function entity_test_entity_test_mul_translation_insert(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mul_translation_insert', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_delete() for 'entity_test_mul'.
|
||||
*/
|
||||
function entity_test_entity_test_mul_translation_delete(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mul_translation_delete', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mulrev'.
|
||||
*/
|
||||
function entity_test_entity_test_mul_changed_translation_insert(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mul_changed_translation_insert', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_delete().
|
||||
*/
|
||||
function entity_test_entity_test_mul_changed_translation_delete(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mul_changed_translation_delete', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_insert().
|
||||
*/
|
||||
function entity_test_entity_test_mulrev_translation_insert(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mulrev_translation_insert', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_delete() for 'entity_test_mulrev'.
|
||||
*/
|
||||
function entity_test_entity_test_mulrev_translation_delete(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mulrev_translation_delete', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mulrev'.
|
||||
*/
|
||||
function entity_test_entity_test_mulrev_changed_translation_insert(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mulrev_changed_translation_insert', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_delete().
|
||||
*/
|
||||
function entity_test_entity_test_mulrev_changed_translation_delete(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mulrev_changed_translation_delete', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mul_langcode_key'.
|
||||
*/
|
||||
function entity_test_entity_test_mul_langcode_key_translation_insert(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mul_langcode_key_translation_insert', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_translation_delete() for 'entity_test_mul_langcode_key'.
|
||||
*/
|
||||
function entity_test_entity_test_mul_langcode_key_translation_delete(EntityInterface $translation) {
|
||||
_entity_test_record_hooks('entity_test_mul_langcode_key_translation_delete', $translation->language()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Field default value callback.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
|
||||
* The entity being created.
|
||||
* @param \Drupal\Core\Field\FieldDefinitionInterface $definition
|
||||
* The field definition.
|
||||
*
|
||||
* @return array
|
||||
* An array of default values, in the same format as the $default_value
|
||||
* property.
|
||||
*
|
||||
* @see \Drupal\field\Entity\FieldConfig::$default_value
|
||||
*/
|
||||
function entity_test_field_default_value(FieldableEntityInterface $entity, FieldDefinitionInterface $definition) {
|
||||
// Include the field name and entity language in the generated values to check
|
||||
// that they are correctly passed.
|
||||
$string = $definition->getName() . '_' . $entity->language()->getId();
|
||||
// Return a "default value" with multiple items.
|
||||
return array(
|
||||
array(
|
||||
'shape' => "shape:0:$string",
|
||||
'color' => "color:0:$string",
|
||||
),
|
||||
array(
|
||||
'shape' => "shape:1:$string",
|
||||
'color' => "color:1:$string",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to be used to record hook invocations.
|
||||
*
|
||||
* @param string $hook
|
||||
* The hook name.
|
||||
* @param mixed $data
|
||||
* Arbitrary data associated to the hook invocation.
|
||||
*/
|
||||
function _entity_test_record_hooks($hook, $data) {
|
||||
$state = \Drupal::state();
|
||||
$key = 'entity_test.hooks';
|
||||
$hooks = $state->get($key);
|
||||
$hooks[$hook] = $data;
|
||||
$state->set($key, $hooks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_prepare_view().
|
||||
*/
|
||||
function entity_test_entity_prepare_view($entity_type, array $entities, array $displays) {
|
||||
// Add a dummy field item attribute on field_test_text if it exists.
|
||||
if ($entity_type == 'entity_test') {
|
||||
foreach ($entities as $entity) {
|
||||
if ($entity->hasField('field_test_text') && $displays[$entity->bundle()]->getComponent('field_test_text')) {
|
||||
foreach ($entity->get('field_test_text') as $item) {
|
||||
$item->_attributes += array('data-field-item-attr' => 'foobar');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_access().
|
||||
*/
|
||||
function entity_test_entity_access(EntityInterface $entity, $operation, AccountInterface $account, $langcode) {
|
||||
\Drupal::state()->set('entity_test_entity_access', TRUE);
|
||||
|
||||
// Attempt to allow access to entities with the title forbid_access,
|
||||
// this will be overridden by
|
||||
// \Drupal\entity_test\EntityTestAccessControlHandler::checkAccess().
|
||||
if ($entity->label() == 'forbid_access') {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
|
||||
// Uncacheable because the access result depends on a State key-value pair and
|
||||
// might therefore change at any time.
|
||||
$condition = \Drupal::state()->get("entity_test_entity_access.{$operation}." . $entity->id(), FALSE);
|
||||
return AccessResult::allowedIf($condition)->setCacheMaxAge(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_access() for 'entity_test'.
|
||||
*/
|
||||
function entity_test_entity_test_access(EntityInterface $entity, $operation, AccountInterface $account, $langcode) {
|
||||
\Drupal::state()->set('entity_test_entity_test_access', TRUE);
|
||||
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_create_access().
|
||||
*/
|
||||
function entity_test_entity_create_access(AccountInterface $account, $context, $entity_bundle) {
|
||||
\Drupal::state()->set('entity_test_entity_create_access', TRUE);
|
||||
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create_access() for 'entity_test'.
|
||||
*/
|
||||
function entity_test_entity_test_create_access(AccountInterface $account, $context, $entity_bundle) {
|
||||
\Drupal::state()->set('entity_test_entity_test_create_access', TRUE);
|
||||
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
administer entity_test content:
|
||||
title: 'Administer entity_test content'
|
||||
description: 'Manage entity_test content'
|
||||
view test entity:
|
||||
title: 'View test entities'
|
||||
view test entity translations:
|
||||
title: 'View translations of test entities'
|
||||
view test entity field:
|
||||
title: 'View test entity field'
|
|
@ -0,0 +1,80 @@
|
|||
entity.entity_test.canonical:
|
||||
path: '/entity_test/{entity_test}'
|
||||
defaults:
|
||||
_entity_view: 'entity_test.full'
|
||||
_title: 'Test full view mode'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.entity_test.render_options:
|
||||
path: '/entity_test_converter/{foo}'
|
||||
options:
|
||||
parameters:
|
||||
foo:
|
||||
type: 'entity:entity_test'
|
||||
defaults:
|
||||
_entity_view: 'entity_test.full'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.entity_test.render_no_view_mode:
|
||||
path: '/entity_test_no_view_mode/{entity_test}'
|
||||
defaults:
|
||||
_entity_view: 'entity_test'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.entity_test.collection_referencing_entities:
|
||||
path: '/entity_test/list/{entity_reference_field_name}/{referenced_entity_type}/{referenced_entity_id}'
|
||||
defaults:
|
||||
_controller: '\Drupal\entity_test\Controller\EntityTestController::listReferencingEntities'
|
||||
_title: 'List entity_test entities referencing the given entity'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.entity_test.collection_labels_alphabetically:
|
||||
path: '/entity_test/list_labels_alphabetically/{entity_type_id}'
|
||||
defaults:
|
||||
_controller: '\Drupal\entity_test\Controller\EntityTestController::listEntitiesAlphabetically'
|
||||
_title: 'List labels of entities of the given entity type alphabetically'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.entity_test.collection_empty:
|
||||
path: '/entity_test/list_empty/{entity_type_id}'
|
||||
defaults:
|
||||
_controller: '\Drupal\entity_test\Controller\EntityTestController::listEntitiesEmpty'
|
||||
_title: 'Empty list of entities of the given entity type, empty because no entities match the query'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.entity_test.collection:
|
||||
path: '/entity_test/list'
|
||||
defaults:
|
||||
_entity_list: entity_test
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.entity_test_rev.revision:
|
||||
path: '/entity_test_rev/{entity_test_rev}/revision/{entity_test_rev_revision}/view'
|
||||
defaults:
|
||||
_entity_view: 'entity_test_rev'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.block.test_operation:
|
||||
path: '/admin/structure/block/manage/{block}/test_operation'
|
||||
defaults:
|
||||
_entity_view: 'entity_test'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
entity.user_role.test_operation:
|
||||
path: '/admin/people/roles/manage/{user_role}/test_operation'
|
||||
defaults:
|
||||
_entity_view: 'entity_test'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
route_callbacks:
|
||||
- '\Drupal\entity_test\Routing\EntityTestRoutes::routes'
|
|
@ -0,0 +1,10 @@
|
|||
services:
|
||||
entity_test.definition.subscriber:
|
||||
class: Drupal\entity_test\EntityTestDefinitionSubscriber
|
||||
arguments: ['@state']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
cache_context.entity_test_view_grants:
|
||||
class: Drupal\entity_test\Cache\EntityTestViewGrantsCacheContext
|
||||
tags:
|
||||
- { name: cache.context }
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_views_data_alter().
|
||||
*/
|
||||
function entity_test_views_data_alter(&$data) {
|
||||
$data['entity_test']['name_alias'] = $data['entity_test']['name'];
|
||||
$data['entity_test']['name_alias']['field']['real field'] = 'name';
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Cache\EntityTestViewGrantsCacheContext.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Cache;
|
||||
|
||||
use Drupal\Core\Cache\Context\CacheContextInterface;
|
||||
|
||||
/**
|
||||
* Defines the entity_test view grants cache context service.
|
||||
*
|
||||
* @see \Drupal\node\Cache\NodeAccessViewGrantsCacheContext
|
||||
*/
|
||||
class EntityTestViewGrantsCacheContext implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getLabel() {
|
||||
return t("Entity test view grants");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
// Return a constant value, so we can fetch render cache both in actual
|
||||
// requests and test code itself.
|
||||
return '299792458';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Controller\EntityTestController.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Controller;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Entity\Query\QueryFactory;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Controller routines for entity_test routes.
|
||||
*/
|
||||
class EntityTestController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The entity query factory.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
*/
|
||||
protected $entityQueryFactory;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityTestController.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\Query\QueryFactory
|
||||
* The entity query factory.
|
||||
*/
|
||||
public function __construct(QueryFactory $entity_query_factory) {
|
||||
$this->entityQueryFactory = $entity_query_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.query')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the 'Add new entity_test' form.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* Name of the entity type for which a create form should be displayed.
|
||||
*
|
||||
* @return array
|
||||
* The processed form for a new entity_test.
|
||||
*
|
||||
* @see \Drupal\entity_test\Routing\EntityTestRoutes::routes()
|
||||
*/
|
||||
public function testAdd($entity_type_id) {
|
||||
$entity = entity_create($entity_type_id, array());
|
||||
$form = $this->entityFormBuilder()->getForm($entity);
|
||||
$form['#title'] = $this->t('Create an @type', array('@type' => $entity_type_id));
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the 'Edit existing entity_test' form.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The route match object to get entity type from.
|
||||
* @param string $entity_type_id
|
||||
* The entity type ID.
|
||||
*
|
||||
* @return array
|
||||
* The processed form for the edited entity.
|
||||
*
|
||||
* @see \Drupal\entity_test\Routing\EntityTestRoutes::routes()
|
||||
*/
|
||||
public function testEdit(RouteMatchInterface $route_match, $entity_type_id) {
|
||||
$entity = $route_match->getParameter($entity_type_id);
|
||||
$form = $this->entityFormBuilder()->getForm($entity);
|
||||
$form['#title'] = $entity->label();
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty page.
|
||||
*
|
||||
* @see \Drupal\entity_test\Routing\EntityTestRoutes::routes()
|
||||
*/
|
||||
public function testAdmin() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* List entity_test entities referencing the given entity.
|
||||
*
|
||||
* @param string $entity_reference_field_name
|
||||
* The name of the entity_reference field to use in the query.
|
||||
* @param string $referenced_entity_type
|
||||
* The type of the entity being referenced.
|
||||
* @param int $referenced_entity_id
|
||||
* The ID of the entity being referenced.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array.
|
||||
*/
|
||||
public function listReferencingEntities($entity_reference_field_name, $referenced_entity_type, $referenced_entity_id) {
|
||||
// Early return if the referenced entity does not exist (or is deleted).
|
||||
$referenced_entity = $this->entityManager()
|
||||
->getStorage($referenced_entity_type)
|
||||
->load($referenced_entity_id);
|
||||
if ($referenced_entity === NULL) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$query = $this->entityQueryFactory
|
||||
->get('entity_test')
|
||||
->condition($entity_reference_field_name . '.target_id', $referenced_entity_id);
|
||||
$entities = $this->entityManager()
|
||||
->getStorage('entity_test')
|
||||
->loadMultiple($query->execute());
|
||||
return $this->entityManager()
|
||||
->getViewBuilder('entity_test')
|
||||
->viewMultiple($entities, 'full');
|
||||
}
|
||||
|
||||
/**
|
||||
* List entities of the given entity type labels, sorted alphabetically.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The type of the entity being listed.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array.
|
||||
*/
|
||||
public function listEntitiesAlphabetically($entity_type_id) {
|
||||
$entity_type_definition = $this->entityManager()->getDefinition($entity_type_id);
|
||||
$query = $this->entityQueryFactory->get($entity_type_id);
|
||||
|
||||
// Sort by label field, if any.
|
||||
if ($label_field = $entity_type_definition->getKey('label')) {
|
||||
$query->sort($label_field);
|
||||
}
|
||||
|
||||
$entities = $this->entityManager()
|
||||
->getStorage($entity_type_id)
|
||||
->loadMultiple($query->execute());
|
||||
|
||||
$cache_tags = [];
|
||||
$labels = [];
|
||||
foreach ($entities as $entity) {
|
||||
$labels[] = $entity->label();
|
||||
$cache_tags = Cache::mergeTags($cache_tags, $entity->getCacheTags());
|
||||
}
|
||||
// Always associate the list cache tag, otherwise the cached empty result
|
||||
// wouldn't be invalidated. This would continue to show nothing matches the
|
||||
// query, even though a newly created entity might match the query.
|
||||
$cache_tags = Cache::mergeTags($cache_tags, $entity_type_definition->getListCacheTags());
|
||||
|
||||
return [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $labels,
|
||||
'#title' => $entity_type_id . ' entities',
|
||||
'#cache' => [
|
||||
'contexts' => $entity_type_definition->getListCacheContexts(),
|
||||
'tags' => $cache_tags,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Empty list of entities of the given entity type.
|
||||
*
|
||||
* Empty because no entities match the query. That may seem contrived, but it
|
||||
* is an excellent way for testing whether an entity's list cache tags are
|
||||
* working as expected.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The type of the entity being listed.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array.
|
||||
*/
|
||||
public function listEntitiesEmpty($entity_type_id) {
|
||||
$entity_type_definition = $this->entityManager()->getDefinition($entity_type_id);
|
||||
return [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => [],
|
||||
'#cache' => [
|
||||
'contexts' => $entity_type_definition->getListCacheContexts(),
|
||||
'tags' => $entity_type_definition->getListCacheTags(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test",
|
||||
* label = @Translation("Test entity"),
|
||||
* handlers = {
|
||||
* "list_builder" = "Drupal\entity_test\EntityTestListBuilder",
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\entity_test\EntityTestViewsData"
|
||||
* },
|
||||
* base_table = "entity_test",
|
||||
* persistent_cache = FALSE,
|
||||
* list_cache_contexts = { "entity_test_view_grants" },
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test/{entity_test}",
|
||||
* "edit-form" = "/entity_test/manage/{entity_test}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test/{entity_test}",
|
||||
* },
|
||||
* field_ui_base_route = "entity.entity_test.admin_form",
|
||||
* )
|
||||
*/
|
||||
class EntityTest extends ContentEntityBase implements EntityOwnerInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function preCreate(EntityStorageInterface $storage, array &$values) {
|
||||
parent::preCreate($storage, $values);
|
||||
if (empty($values['type'])) {
|
||||
$values['type'] = $storage->getEntityTypeId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields['id'] = BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('ID'))
|
||||
->setDescription(t('The ID of the test entity.'))
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE);
|
||||
|
||||
$fields['uuid'] = BaseFieldDefinition::create('uuid')
|
||||
->setLabel(t('UUID'))
|
||||
->setDescription(t('The UUID of the test entity.'))
|
||||
->setReadOnly(TRUE);
|
||||
|
||||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language code'))
|
||||
->setDescription(t('The language code of the test entity.'))
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
$fields['name'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('Name'))
|
||||
->setDescription(t('The name of the test entity.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setSetting('max_length', 32)
|
||||
->setDisplayOptions('view', array(
|
||||
'label' => 'hidden',
|
||||
'type' => 'string',
|
||||
'weight' => -5,
|
||||
))
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'string_textfield',
|
||||
'weight' => -5,
|
||||
));
|
||||
|
||||
// @todo: Add allowed values validation.
|
||||
$fields['type'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('Type'))
|
||||
->setDescription(t('The bundle of the test entity.'))
|
||||
->setRequired(TRUE);
|
||||
|
||||
$fields['created'] = BaseFieldDefinition::create('created')
|
||||
->setLabel(t('Authored on'))
|
||||
->setDescription(t('Time the entity was created'))
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
$fields['user_id'] = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(t('User ID'))
|
||||
->setDescription(t('The ID of the associated user.'))
|
||||
->setSetting('target_type', 'user')
|
||||
->setSetting('handler', 'default')
|
||||
// Default EntityTest entities to have the root user as the owner, to
|
||||
// simplify testing.
|
||||
->setDefaultValue(array(0 => array('target_id' => 1)))
|
||||
->setTranslatable(TRUE)
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'entity_reference_autocomplete',
|
||||
'weight' => -1,
|
||||
'settings' => array(
|
||||
'match_operator' => 'CONTAINS',
|
||||
'size' => '60',
|
||||
'placeholder' => '',
|
||||
),
|
||||
));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOwner() {
|
||||
return $this->get('user_id')->entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOwnerId() {
|
||||
return $this->get('user_id')->target_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOwnerId($uid) {
|
||||
$this->set('user_id', $uid);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOwner(UserInterface $account) {
|
||||
$this->set('user_id', $account->id());
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name.
|
||||
*
|
||||
* @param string $name
|
||||
* Name of the entity.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($name) {
|
||||
$this->set('name', $name);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->get('name')->value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestBaseFieldDisplay.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines a test entity class for base fields display.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_base_field_display",
|
||||
* label = @Translation("Test entity - base field display"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler"
|
||||
* },
|
||||
* base_table = "entity_test",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type"
|
||||
* },
|
||||
* links = {
|
||||
* "edit-form" = "/entity_test_base_field_display/manage/{entity_test_base_field_display}",
|
||||
* },
|
||||
* field_ui_base_route = "entity.entity_test_base_field_display.admin_form",
|
||||
* )
|
||||
*/
|
||||
class EntityTestBaseFieldDisplay extends EntityTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['test_no_display'] = BaseFieldDefinition::create('text')
|
||||
->setLabel(t('Field with no display'));
|
||||
|
||||
$fields['test_display_configurable'] = BaseFieldDefinition::create('text')
|
||||
->setLabel(t('Field with configurable display'))
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'text_default',
|
||||
'weight' => 10,
|
||||
))
|
||||
->setDisplayConfigurable('view', TRUE)
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'text_textfield',
|
||||
'weight' => 10,
|
||||
))
|
||||
->setDisplayConfigurable('form', TRUE);
|
||||
|
||||
$fields['test_display_non_configurable'] = BaseFieldDefinition::create('text')
|
||||
->setLabel(t('Field with non-configurable display'))
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'text_default',
|
||||
'weight' => 11,
|
||||
))
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'text_textfield',
|
||||
'weight' => 11,
|
||||
));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestCache.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_cache",
|
||||
* label = @Translation("Test entity with field cache"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler"
|
||||
* },
|
||||
* base_table = "entity_test",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestCache extends EntityTest {
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestCompositeConstraint.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Defines a test class for testing composite constraints.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_composite_constraint",
|
||||
* label = @Translation("Test entity constraints with composite constraint"),
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name"
|
||||
* },
|
||||
* handlers = {
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm"
|
||||
* }
|
||||
* },
|
||||
* base_table = "entity_test_composite_constraint",
|
||||
* persistent_cache = FALSE,
|
||||
* constraints = {
|
||||
* "EntityTestComposite" = {},
|
||||
* "EntityTestEntityLevel" = {},
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestCompositeConstraint extends EntityTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['name']->setDisplayOptions('form', array(
|
||||
'type' => 'string',
|
||||
'weight' => 0,
|
||||
));
|
||||
|
||||
$fields['type']->setDisplayOptions('form', array(
|
||||
'type' => 'entity_reference_autocomplete',
|
||||
'weight' => 0,
|
||||
));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestConstraintViolation.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Defines the test entity class for testing entity constraint violations.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_constraint_violation",
|
||||
* label = @Translation("Test entity constraint violation"),
|
||||
* handlers = {
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm"
|
||||
* }
|
||||
* },
|
||||
* base_table = "entity_test",
|
||||
* persistent_cache = FALSE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestConstraintViolation extends EntityTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['name']->setDisplayOptions('form', array(
|
||||
'type' => 'string',
|
||||
'weight' => 0,
|
||||
));
|
||||
$fields['name']->addConstraint('FieldWidgetConstraint', array());
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestConstraints.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityChangedTrait;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityChangedInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines a test class for testing the definition of entity level constraints.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_constraints",
|
||||
* label = @Translation("Test entity constraints"),
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name"
|
||||
* },
|
||||
* base_table = "entity_test_constraints",
|
||||
* persistent_cache = FALSE,
|
||||
* constraints = {
|
||||
* "NotNull" = {}
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestConstraints extends EntityTest implements EntityChangedInterface {
|
||||
|
||||
use EntityChangedTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['changed'] = BaseFieldDefinition::create('changed')
|
||||
->setLabel(t('Changed'));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getChangedTime() {
|
||||
return $this->get('changed')->value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestDefaultAccess.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
/**
|
||||
* Defines a test entity class with no access control handler.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_default_access",
|
||||
* label = @Translation("Test entity with default access"),
|
||||
* base_table = "entity_test",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "bundle" = "type"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestDefaultAccess extends EntityTest {
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestDefaultValue.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines a test entity class for testing default values.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_default_value",
|
||||
* label = @Translation("Test entity for default values"),
|
||||
* base_table = "entity_test_default_value",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "langcode" = "langcode"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestDefaultValue extends EntityTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['description'] = BaseFieldDefinition::create('shape')
|
||||
->setLabel(t('Some custom description'))
|
||||
->setDefaultValueCallback('entity_test_field_default_value');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestFieldOverride.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Defines a test entity class for testing default values.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_field_override",
|
||||
* label = @Translation("Test entity field overrides"),
|
||||
* base_table = "entity_test_field_override",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestFieldOverride extends EntityTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
$fields['name']->setDescription('The default description.');
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
|
||||
$fields = parent::bundleFieldDefinitions($entity_type, $bundle, $base_field_definitions);
|
||||
|
||||
if ($bundle == 'some_test_bundle') {
|
||||
$fields['name'] = clone $base_field_definitions['name'];
|
||||
$fields['name']->setDescription('Custom description.');
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestLabel.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
/**
|
||||
* Test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_label",
|
||||
* label = @Translation("Entity Test label"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder"
|
||||
* },
|
||||
* base_table = "entity_test",
|
||||
* render_cache = FALSE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "label" = "name",
|
||||
* "bundle" = "type"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestLabel extends EntityTest {
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestLabelCallback.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
/**
|
||||
* Test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_label_callback",
|
||||
* label = @Translation("Entity test label callback"),
|
||||
* persistent_cache = FALSE,
|
||||
* base_table = "entity_test",
|
||||
* label_callback = "entity_test_label_callback",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "bundle" = "type"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestLabelCallback extends EntityTest {
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestMul.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_mul",
|
||||
* label = @Translation("Test entity - data table"),
|
||||
* handlers = {
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\views\EntityViewsData"
|
||||
* },
|
||||
* base_table = "entity_test_mul",
|
||||
* data_table = "entity_test_mul_property_data",
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test_mul/manage/{entity_test_mul}",
|
||||
* "edit-form" = "/entity_test_mul/manage/{entity_test_mul}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mul/{entity_test_mul}",
|
||||
* },
|
||||
* field_ui_base_route = "entity.entity_test_mul.admin_form",
|
||||
* )
|
||||
*/
|
||||
class EntityTestMul extends EntityTest {
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestMulChanged.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityChangedInterface;
|
||||
use Drupal\Core\Entity\EntityChangedTrait;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_mul_changed",
|
||||
* label = @Translation("Test entity - data table"),
|
||||
* handlers = {
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\views\EntityViewsData"
|
||||
* },
|
||||
* base_table = "entity_test_mul_changed",
|
||||
* data_table = "entity_test_mul_changed_property",
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode"
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test_mul_changed/manage/{entity_test_mul_changed}",
|
||||
* "edit-form" = "/entity_test_mul_changed/manage/{entity_test_mul_changed}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mul_changed/{entity_test_mul_changed}",
|
||||
* },
|
||||
* field_ui_base_route = "entity.entity_test_mul_changed.admin_form",
|
||||
* )
|
||||
*/
|
||||
class EntityTestMulChanged extends EntityTestMul implements EntityChangedInterface {
|
||||
|
||||
use EntityChangedTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['changed'] = BaseFieldDefinition::create('changed_test')
|
||||
->setLabel(t('Changed'))
|
||||
->setDescription(t('The time that the entity was last edited.'))
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save() {
|
||||
// Ensure a new timestamp.
|
||||
sleep(1);
|
||||
parent::save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getChangedTime() {
|
||||
return $this->get('changed')->value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestMulDefaultValue.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_mul_default_value",
|
||||
* label = @Translation("Test entity - data table"),
|
||||
* handlers = {
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\views\EntityViewsData"
|
||||
* },
|
||||
* base_table = "entity_test_mul_default_value",
|
||||
* data_table = "entity_test_mul_default_value_property_data",
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode"
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test_mul_default_value/manage/{entity_test_mul_default_value}",
|
||||
* "edit-form" = "/entity_test_mul_default_value/manage/{entity_test_mul_default_value}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mul_default_value/{entity_test_mul_default_value}",
|
||||
* },
|
||||
* field_ui_base_route = "entity.entity_test_mul.admin_form",
|
||||
* )
|
||||
*/
|
||||
class EntityTestMulDefaultValue extends EntityTestMul {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['description'] = BaseFieldDefinition::create('shape')
|
||||
->setLabel(t('Some custom description'))
|
||||
->setTranslatable(TRUE)
|
||||
->setDefaultValueCallback('entity_test_field_default_value');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestMulLangcodeKey.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Defines a test entity class using a custom langcode entity key.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_mul_langcode_key",
|
||||
* label = @Translation("Test entity - data table - langcode key"),
|
||||
* handlers = {
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\views\EntityViewsData"
|
||||
* },
|
||||
* base_table = "entity_test_mul_langcode_key",
|
||||
* data_table = "entity_test_mul_langcode_key_field_data",
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "custom_langcode_key",
|
||||
* "default_langcode" = "custom_default_langcode_key",
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}",
|
||||
* "edit-form" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mul_langcode_key/{entity_test_mul_langcode_key}",
|
||||
* },
|
||||
* field_ui_base_route = "entity.entity_test_mul_langcode_key.admin_form",
|
||||
* )
|
||||
*/
|
||||
class EntityTestMulLangcodeKey extends EntityTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
$fields['custom_langcode_key'] = $fields['langcode'];
|
||||
unset($fields['langcode']);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestMulRev.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\entity_test\Entity\EntityTestRev;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_mulrev",
|
||||
* label = @Translation("Test entity - revisions and data table"),
|
||||
* handlers = {
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\views\EntityViewsData"
|
||||
* },
|
||||
* base_table = "entity_test_mulrev",
|
||||
* data_table = "entity_test_mulrev_property_data",
|
||||
* revision_table = "entity_test_mulrev_revision",
|
||||
* revision_data_table = "entity_test_mulrev_property_revision",
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "revision" = "revision_id",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test_mulrev/manage/{entity_test_mulrev}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mulrev/{entity_test_mulrev}",
|
||||
* "edit-form" = "/entity_test_mulrev/manage/{entity_test_mulrev}",
|
||||
* "revision" = "/entity_test_mulrev/{entity_test_mulrev}/revision/{entity_test_mulrev_revision}/view",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestMulRev extends EntityTestRev {
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestMulRevChanged.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_mulrev_changed",
|
||||
* label = @Translation("Test entity - revisions and data table"),
|
||||
* handlers = {
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\views\EntityViewsData"
|
||||
* },
|
||||
* base_table = "entity_test_mulrev_changed",
|
||||
* data_table = "entity_test_mulrev_changed_property",
|
||||
* revision_table = "entity_test_mulrev_changed_revision",
|
||||
* revision_data_table = "entity_test_mulrev_changed_property_revision",
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "revision" = "revision_id",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test_mulrev_changed/manage/{entity_test_mulrev_changed}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mulrev_changed/{entity_test_mulrev_changed}",
|
||||
* "edit-form" = "/entity_test_mulrev_changed/manage/{entity_test_mulrev_changed}",
|
||||
* "revision" = "/entity_test_mulrev_changed/{entity_test_mulrev_changed}/revision/{entity_test_mulrev_changed_revision}/view",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestMulRevChanged extends EntityTestMulChanged {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['revision_id'] = BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('Revision ID'))
|
||||
->setDescription(t('The version id of the test entity.'))
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE);
|
||||
|
||||
$fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('Revision translation affected'))
|
||||
->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
|
||||
->setReadOnly(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
$fields['langcode']->setRevisionable(TRUE);
|
||||
$fields['name']->setRevisionable(TRUE);
|
||||
$fields['user_id']->setRevisionable(TRUE);
|
||||
$fields['changed']->setRevisionable(TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\entity_test\Entity\EntityTestNew.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
/**
|
||||
* Defines the test entity class for testing definition addition.
|
||||
*
|
||||
* This entity type is initially not defined. It is enabled when needed to test
|
||||
* the related updates.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_new",
|
||||
* label = @Translation("New test entity"),
|
||||
* base_table = "entity_test_new",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class EntityTestNew extends EntityTest {
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue