Commit a61f62b4 authored by webchick's avatar webchick
Browse files

Issue #1798944 by kbasarab, sun, tim.plunkett, andypost: Convert config_test()...

Issue #1798944 by kbasarab, sun, tim.plunkett, andypost: Convert config_test() entity forms to EntityFormController.
parent 0142ce1f
......@@ -32,8 +32,10 @@ public function __construct(array $values, $entity_type) {
parent::__construct($values, $entity_type);
// Backup the original ID, if any.
if ($original_id = $this->id()) {
$this->originalID = $original_id;
// Configuration entity IDs are strings, and '0' is a valid ID.
$original_id = $this->id();
if ($original_id !== NULL && $original_id !== '') {
$this->setOriginalID($original_id);
}
}
......@@ -45,23 +47,22 @@ public function getOriginalID() {
}
/**
* Overrides Entity::isNew().
*
* EntityInterface::enforceIsNew() is not supported by configuration entities,
* since each configuration entity is unique.
* Implements ConfigEntityInterface::setOriginalID().
*/
final public function isNew() {
return !$this->id();
public function setOriginalID($id) {
$this->originalID = $id;
}
/**
* Overrides Entity::bundle().
* Overrides Entity::isNew().
*
* EntityInterface::bundle() is not supported by configuration entities, since
* a configuration entity is a bundle.
* EntityInterface::enforceIsNew() is only supported for newly created
* configuration entities but has no effect after saving, since each
* configuration entity is unique.
*/
final public function bundle() {
return $this->entityType;
final public function isNew() {
// Configuration entity IDs are strings, and '0' is a valid ID.
return !empty($this->enforceIsNew) || $this->id() === NULL || $this->id() === '';
}
/**
......@@ -86,6 +87,16 @@ public function set($property_name, $value, $langcode = NULL) {
$this->{$property_name} = $value;
}
/**
* Overrides Entity::createDuplicate().
*/
public function createDuplicate() {
$duplicate = parent::createDuplicate();
// Prevent the new duplicate from being misinterpreted as a rename.
$duplicate->setOriginalID(NULL);
return $duplicate;
}
/**
* Helper callback for uasort() to sort configuration entities by weight and label.
*/
......
......@@ -22,4 +22,14 @@ interface ConfigEntityInterface extends EntityInterface {
*/
public function getOriginalID();
/**
* Sets the original ID.
*
* @param string $id
* The new ID to set as original ID.
*
* @return void
*/
public function setOriginalID($id);
}
......@@ -9,6 +9,7 @@
use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityMalformedException;
use Drupal\Core\Entity\EntityStorageControllerInterface;
/**
......@@ -222,6 +223,9 @@ public function create(array $values) {
$class = isset($this->entityInfo['entity class']) ? $this->entityInfo['entity class'] : 'Drupal\Core\Entity\Entity';
$entity = new $class($values, $this->entityType);
// Mark this entity as new, so isNew() returns TRUE. This does not check
// whether a configuration entity with the same ID (if any) already exists.
$entity->enforceIsNew();
// Assign a new UUID if there is none yet.
if (!isset($entity->{$this->uuidKey})) {
......@@ -260,22 +264,31 @@ public function delete($ids) {
/**
* Implements Drupal\Core\Entity\EntityStorageControllerInterface::save().
*
* @throws EntityMalformedException
* When attempting to save a configuration entity that has no ID.
*/
public function save(EntityInterface $entity) {
$prefix = $this->entityInfo['config prefix'] . '.';
// Configuration entity IDs are strings, and '0' is a valid ID.
$id = $entity->id();
if ($id === NULL || $id === '') {
throw new EntityMalformedException('The entity does not have an ID.');
}
// Load the stored entity, if any.
if ($entity->getOriginalID()) {
// At this point, the original ID can only be NULL or a valid ID.
if ($entity->getOriginalID() !== NULL) {
$id = $entity->getOriginalID();
}
else {
$id = $entity->id();
}
$config = config($prefix . $id);
$config->setName($prefix . $entity->id());
if (!$config->isNew() && !isset($entity->original)) {
$entity->original = entity_load_unchanged($this->entityType, $id);
$this->resetCache(array($id));
$result = $this->load(array($id));
$entity->original = reset($result);
}
$this->preSave($entity);
......@@ -291,6 +304,9 @@ public function save(EntityInterface $entity) {
$config->save();
$this->postSave($entity, TRUE);
$this->invokeHook('update', $entity);
// Immediately update the original ID.
$entity->setOriginalID($entity->id());
}
else {
$return = SAVED_NEW;
......
......@@ -145,7 +145,7 @@ function testListUI() {
$this->assertLink('Edit');
$this->clickLink('Edit');
$this->assertResponse(200);
$this->assertTitle('Edit test configuration | Drupal');
$this->assertTitle('Edit Antelope | Drupal');
$edit = array('label' => 'Albatross', 'id' => 'albatross');
$this->drupalPost(NULL, $edit, t('Save'));
......
......@@ -7,6 +7,7 @@
namespace Drupal\config\Tests;
use Drupal\Core\Entity\EntityMalformedException;
use Drupal\simpletest\WebTestBase;
/**
......@@ -30,13 +31,163 @@ public static function getInfo() {
}
/**
* Tests basic CRUD operations through the UI.
* Tests CRUD operations.
*/
function testCRUD() {
// Verify default properties on a newly created empty entity.
$empty = entity_create('config_test', array());
$this->assertIdentical($empty->id, NULL);
$this->assertTrue($empty->uuid);
$this->assertIdentical($empty->label, NULL);
$this->assertIdentical($empty->style, NULL);
$this->assertIdentical($empty->langcode, LANGUAGE_NOT_SPECIFIED);
// Verify ConfigEntity properties/methods on the newly created empty entity.
$this->assertIdentical($empty->isNew(), TRUE);
$this->assertIdentical($empty->getOriginalID(), NULL);
$this->assertIdentical($empty->bundle(), 'config_test');
$this->assertIdentical($empty->id(), NULL);
$this->assertTrue($empty->uuid());
$this->assertIdentical($empty->label(), NULL);
$this->assertIdentical($empty->get('id'), NULL);
$this->assertTrue($empty->get('uuid'));
$this->assertIdentical($empty->get('label'), NULL);
$this->assertIdentical($empty->get('style'), NULL);
$this->assertIdentical($empty->get('langcode'), LANGUAGE_NOT_SPECIFIED);
// Verify Entity properties/methods on the newly created empty entity.
$this->assertIdentical($empty->isNewRevision(), FALSE);
$this->assertIdentical($empty->entityType(), 'config_test');
$uri = $empty->uri();
$this->assertIdentical($uri['path'], 'admin/structure/config_test/manage/');
$this->assertIdentical($empty->isDefaultRevision(), TRUE);
// Verify that an empty entity cannot be saved.
try {
$empty->save();
$this->fail('EntityMalformedException was thrown.');
}
catch (EntityMalformedException $e) {
$this->pass('EntityMalformedException was thrown.');
}
// Verify that an entity with an empty ID string is considered empty, too.
$empty_id = entity_create('config_test', array(
'id' => '',
));
$this->assertIdentical($empty_id->isNew(), TRUE);
try {
$empty_id->save();
$this->fail('EntityMalformedException was thrown.');
}
catch (EntityMalformedException $e) {
$this->pass('EntityMalformedException was thrown.');
}
// Verify properties on a newly created entity.
$config_test = entity_create('config_test', $expected = array(
'id' => $this->randomName(),
'label' => $this->randomString(),
'style' => $this->randomName(),
));
$this->assertIdentical($config_test->id, $expected['id']);
$this->assertTrue($config_test->uuid);
$this->assertNotEqual($config_test->uuid, $empty->uuid);
$this->assertIdentical($config_test->label, $expected['label']);
$this->assertIdentical($config_test->style, $expected['style']);
$this->assertIdentical($config_test->langcode, LANGUAGE_NOT_SPECIFIED);
// Verify methods on the newly created entity.
$this->assertIdentical($config_test->isNew(), TRUE);
$this->assertIdentical($config_test->getOriginalID(), $expected['id']);
$this->assertIdentical($config_test->id(), $expected['id']);
$this->assertTrue($config_test->uuid());
$expected['uuid'] = $config_test->uuid();
$this->assertIdentical($config_test->label(), $expected['label']);
$this->assertIdentical($config_test->isNewRevision(), FALSE);
$uri = $config_test->uri();
$this->assertIdentical($uri['path'], 'admin/structure/config_test/manage/' . $expected['id']);
$this->assertIdentical($config_test->isDefaultRevision(), TRUE);
// Verify that the entity can be saved.
try {
$status = $config_test->save();
$this->pass('EntityMalformedException was not thrown.');
}
catch (EntityMalformedException $e) {
$this->fail('EntityMalformedException was not thrown.');
}
// Verify that the correct status is returned and properties did not change.
$this->assertIdentical($status, SAVED_NEW);
$this->assertIdentical($config_test->id(), $expected['id']);
$this->assertIdentical($config_test->uuid(), $expected['uuid']);
$this->assertIdentical($config_test->label(), $expected['label']);
$this->assertIdentical($config_test->isNew(), FALSE);
$this->assertIdentical($config_test->getOriginalID(), $expected['id']);
// Save again, and verify correct status and properties again.
$status = $config_test->save();
$this->assertIdentical($status, SAVED_UPDATED);
$this->assertIdentical($config_test->id(), $expected['id']);
$this->assertIdentical($config_test->uuid(), $expected['uuid']);
$this->assertIdentical($config_test->label(), $expected['label']);
$this->assertIdentical($config_test->isNew(), FALSE);
$this->assertIdentical($config_test->getOriginalID(), $expected['id']);
// Re-create the entity with the same ID and verify updated status.
$same_id = entity_create('config_test', array(
'id' => $config_test->id(),
));
$this->assertIdentical($same_id->isNew(), TRUE);
$status = $same_id->save();
$this->assertIdentical($status, SAVED_UPDATED);
// Verify that the entity was overwritten.
$same_id = entity_load('config_test', $config_test->id());
$this->assertIdentical($same_id->id(), $config_test->id());
// Note: Reloading loads from FileStorage, and FileStorage enforces strings.
$this->assertIdentical($same_id->label(), '');
$this->assertNotEqual($same_id->uuid(), $config_test->uuid());
// Revert to previous state.
$config_test->save();
// Verify that renaming the ID returns correct status and properties.
$ids = array($expected['id'], 'second_' . $this->randomName(4), 'third_' . $this->randomName(4));
for ($i = 1; $i < 3; $i++) {
$old_id = $ids[$i - 1];
$new_id = $ids[$i];
// Before renaming, everything should point to the current ID.
$this->assertIdentical($config_test->id(), $old_id);
$this->assertIdentical($config_test->getOriginalID(), $old_id);
// Rename.
$config_test->id = $new_id;
$this->assertIdentical($config_test->id(), $new_id);
$status = $config_test->save();
$this->assertIdentical($status, SAVED_UPDATED);
$this->assertIdentical($config_test->isNew(), FALSE);
// Verify that originalID points to new ID directly after renaming.
$this->assertIdentical($config_test->id(), $new_id);
$this->assertIdentical($config_test->getOriginalID(), $new_id);
}
}
/**
* Tests CRUD operations through the UI.
*/
function testCRUDUI() {
$id = strtolower($this->randomName());
$label1 = $this->randomName();
$label2 = $this->randomName();
$label3 = $this->randomName();
$message_insert = format_string('%label configuration has been created.', array('%label' => $label1));
$message_update = format_string('%label configuration has been updated.', array('%label' => $label2));
$message_delete = format_string('%label configuration has been deleted.', array('%label' => $label2));
// Create a configuration entity.
$edit = array(
......@@ -44,27 +195,36 @@ function testCRUD() {
'label' => $label1,
);
$this->drupalPost('admin/structure/config_test/add', $edit, 'Save');
$this->assertUrl('admin/structure/config_test');
$this->assertResponse(200);
$message_insert = format_string('%label configuration has been created.', array('%label' => $label1));
$this->assertRaw($message_insert);
$this->assertNoRaw($message_update);
$this->assertLinkByHref("admin/structure/config_test/manage/$id/edit");
// Update the configuration entity.
$this->assertLinkByHref('admin/structure/config_test/manage/' . $id);
$edit = array(
'label' => $label2,
);
$this->drupalPost('admin/structure/config_test/manage/' . $id, $edit, 'Save');
$this->drupalPost("admin/structure/config_test/manage/$id", $edit, 'Save');
$this->assertUrl('admin/structure/config_test');
$this->assertResponse(200);
$message_update = format_string('%label configuration has been updated.', array('%label' => $label2));
$this->assertNoRaw($message_insert);
$this->assertRaw($message_update);
$this->assertLinkByHref("admin/structure/config_test/manage/$id/edit");
$this->assertLinkByHref("admin/structure/config_test/manage/$id/delete");
// Delete the configuration entity.
$this->assertLinkByHref('admin/structure/config_test/manage/' . $id . '/delete');
$this->drupalPost('admin/structure/config_test/manage/' . $id . '/delete', array(), 'Delete');
$this->drupalGet("admin/structure/config_test/manage/$id/edit");
$this->drupalPost(NULL, array(), 'Delete');
$this->assertUrl("admin/structure/config_test/manage/$id/delete");
$this->drupalPost(NULL, array(), 'Delete');
$this->assertUrl('admin/structure/config_test');
$this->assertResponse(200);
$this->assertNoRaw($message_update);
$this->assertRaw($message_delete);
$this->assertNoText($label1);
$this->assertNoText($label2);
$this->assertNoLinkByHref("admin/structure/config_test/manage/$id");
$this->assertNoLinkByHref("admin/structure/config_test/manage/$id/edit");
// Re-create a configuration entity.
$edit = array(
......@@ -72,19 +232,26 @@ function testCRUD() {
'label' => $label1,
);
$this->drupalPost('admin/structure/config_test/add', $edit, 'Save');
$this->assertUrl('admin/structure/config_test');
$this->assertResponse(200);
$this->assertText($label1);
$this->assertLinkByHref("admin/structure/config_test/manage/$id/edit");
// Rename the configuration entity's ID/machine name.
$this->assertLinkByHref('admin/structure/config_test/manage/' . $id);
$edit = array(
'id' => strtolower($this->randomName()),
'label' => $label3,
);
$this->drupalPost('admin/structure/config_test/manage/' . $id, $edit, 'Save');
$this->drupalPost("admin/structure/config_test/manage/$id", $edit, 'Save');
$this->assertUrl('admin/structure/config_test');
$this->assertResponse(200);
$this->assertNoText($label1);
$this->assertNoText($label2);
$this->assertText($label3);
$this->assertNoLinkByHref("admin/structure/config_test/manage/$id");
$this->assertNoLinkByHref("admin/structure/config_test/manage/$id/edit");
$id = $edit['id'];
$this->assertLinkByHref("admin/structure/config_test/manage/$id/edit");
}
}
......@@ -35,9 +35,7 @@ function config_test_config_import_change($name, $new_config, $old_config) {
$GLOBALS['hook_config_import'] = __FUNCTION__;
// @todo Make this less ugly.
list($entity_type) = explode('.', $name);
$entity_info = entity_get_info($entity_type);
$id = substr($name, strlen($entity_info['config prefix']) + 1);
list(, , $id) = explode('.', $name);
$config_test = entity_load('config_test', $id);
// Store the original config, and iterate through each property to store it.
......@@ -67,10 +65,9 @@ function config_test_config_import_delete($name, $new_config, $old_config) {
$GLOBALS['hook_config_import'] = __FUNCTION__;
// @todo Make this less ugly.
list($entity_type) = explode('.', $name);
$entity_info = entity_get_info($entity_type);
$id = substr($name, strlen($entity_info['config prefix']) + 1);
config_test_delete($id);
list(, , $id) = explode('.', $name);
$config_test = entity_load('config_test', $id);
$config_test->delete();
return TRUE;
}
......@@ -83,6 +80,9 @@ function config_test_entity_info() {
'controller class' => 'Drupal\Core\Config\Entity\ConfigStorageController',
'entity class' => 'Drupal\config_test\ConfigTest',
'list controller class' => 'Drupal\Core\Config\Entity\ConfigEntityListController',
'form controller class' => array(
'default' => 'Drupal\config_test\ConfigTestFormController',
),
'uri callback' => 'config_test_uri',
'config prefix' => 'config_test.dynamic',
'entity keys' => array(
......@@ -117,15 +117,14 @@ function config_test_menu() {
);
$items['admin/structure/config_test/add'] = array(
'title' => 'Add test configuration',
'page callback' => 'drupal_get_form',
'page arguments' => array('config_test_form'),
'page callback' => 'config_test_add_page',
'access callback' => TRUE,
'type' => MENU_LOCAL_ACTION,
);
$items['admin/structure/config_test/manage/%config_test'] = array(
'title' => 'Edit test configuration',
'page callback' => 'drupal_get_form',
'page arguments' => array('config_test_form', 4),
'page callback' => 'config_test_edit_page',
'page arguments' => array(4),
'access callback' => TRUE,
);
$items['admin/structure/config_test/manage/%config_test/edit'] = array(
......@@ -153,26 +152,6 @@ function config_test_load($id) {
return entity_load('config_test', $id);
}
/**
* Saves a ConfigTest object.
*
* @param Drupal\config_test\ConfigTest $config_test
* The ConfigTest object to save.
*/
function config_test_save(ConfigTest $config_test) {
return $config_test->save();
}
/**
* Deletes a ConfigTest object.
*
* @param string $id
* The ID of the ConfigTest object to delete.
*/
function config_test_delete($id) {
entity_delete_multiple('config_test', array($id));
}
/**
* Page callback; Lists available ConfigTest objects.
*/
......@@ -182,77 +161,28 @@ function config_test_list_page() {
}
/**
* Form constructor to add or edit a ConfigTest object.
* Page callback: Presents the ConfigTest creation form.
*
* @param Drupal\config_test\ConfigTest $config_test
* (optional) An existing ConfigTest object to edit. If omitted, the form
* creates a new ConfigTest.
* @return array
* A form array as expected by drupal_render().
*/
function config_test_form($form, &$form_state, ConfigTest $config_test = NULL) {
// Standard procedure for handling the entity argument in entity forms, taking
// potential form caching and rebuilds properly into account.
// @see http://drupal.org/node/1499596
if (!isset($form_state['config_test'])) {
if (!isset($config_test)) {
$config_test = entity_create('config_test', array());
}
$form_state['config_test'] = $config_test;
}
else {
$config_test = $form_state['config_test'];
}
$form['label'] = array(
'#type' => 'textfield',
'#title' => 'Label',
'#default_value' => $config_test->label(),
'#required' => TRUE,
);
$form['id'] = array(
'#type' => 'machine_name',
'#default_value' => $config_test->id(),
'#required' => TRUE,
'#machine_name' => array(
'exists' => 'config_test_load',
),
);
$form['style'] = array(
'#type' => 'select',
'#title' => 'Image style',
'#options' => array(),
'#default_value' => $config_test->get('style'),
'#access' => FALSE,
);
if (module_exists('image')) {
$form['style']['#access'] = TRUE;
$form['style']['#options'] = image_style_options();
}
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array('#type' => 'submit', '#value' => 'Save');
return $form;
function config_test_add_page() {
$entity = entity_create('config_test', array());
return entity_get_form($entity);
}
/**
* Form submission handler for config_test_form().
* Page callback: Presents the ConfigTest edit form.
*
* @param Drupal\config_test\ConfigTest $config_test
* The ConfigTest object to edit.
*
* @return array
* A form array as expected by drupal_render().
*/
function config_test_form_submit($form, &$form_state) {
form_state_values_clean($form_state);
$config_test = $form_state['config_test'];
entity_form_submit_build_entity('config_test', $config_test, $form, $form_state);
$status = $config_test->save();
if ($status == SAVED_UPDATED) {
drupal_set_message(format_string('%label configuration has been updated.', array('%label' => $config_test->label())));
}
else {
drupal_set_message(format_string('%label configuration has been created.', array('%label' => $config_test->label())));
}
$form_state['redirect'] = 'admin/structure/config_test';
function config_test_edit_page(ConfigTest $config_test) {
drupal_set_title(format_string('Edit %label', array('%label' => $config_test->label())), PASS_THROUGH);
return entity_get_form($config_test);
}
/**
......@@ -278,5 +208,6 @@ function config_test_delete_form($form, &$form_state, ConfigTest $config_test) {
*/
function config_test_delete_form_submit($form, &$form_state) {
$form_state['config_test']->delete();
drupal_set_message(format_string('%label configuration has been deleted.', array('%label' => $form_state['config_test']->label())));
$form_state['redirect'] = 'admin/structure/config_test';
}
<?php
/**
* @file
* Contains Drupal\config_test\ConfigTestFormController.
*/
namespace Drupal\config_test;