diff -u b/config_entity_example/lib/Drupal/config_entity_example/Form/RobotFormBase.php b/config_entity_example/lib/Drupal/config_entity_example/Form/RobotFormBase.php --- b/config_entity_example/lib/Drupal/config_entity_example/Form/RobotFormBase.php +++ b/config_entity_example/lib/Drupal/config_entity_example/Form/RobotFormBase.php @@ -8,7 +8,9 @@ namespace Drupal\config_entity_example\Form; use Drupal\Core\Url; -use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Entity\EntityForm; +use \Drupal\Core\Entity\Query\QueryFactory; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Class RobotFormBase. @@ -22,7 +24,46 @@ * * @ingroup config_entity_example */ -class RobotFormBase extends EntityFormController { +class RobotFormBase extends EntityForm { + + /** + * @var \Drupal\Core\Entity\Query\QueryFactory + */ + protected $entityQueryFactory; + + /** + * Construct the RobotFormBase. + * + * For simple entity forms, there's no need for a constructor. Our robot form + * base, however, requires an entity query factory to be injected into it + * from the container. We later use this query factory to build an entity + * query for the exists() method. + * + * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory + * An entity query factory for the robot entity type. + */ + public function __construct(QueryFactory $query_factory) { + $this->entityQueryFactory = $query_factory; + } + + /** + * Factory method for RobotFormBase. + * + * When Drupal builds this class it does not call the constructor directly. + * Instead, it relies on this method to build the new object. Why? The class + * constructor may take multiple arguments that are unknown to Drupal. The + * create() method always takes one parameter -- the container. The purpose + * of the create() method is twofold: It provides a standard way for Drupal + * to construct the object, meanwhile it provides you a place to get needed + * constructor parameters from the container. + * + * In this case, we ask the container for an entity query factory. We then + * pass the factory to our class as a constructor parameter. + * + */ + public static function create(ContainerInterface $container) { + return new static($container->get('entity.query')); + } /** * Overrides Drupal\Core\Entity\EntityFormController::form(). @@ -61,7 +102,9 @@ '#title' => $this->t('Machine name'), '#default_value' => $robot->id(), '#machine_name' => array( - 'exists' => 'contact_category_load', + 'exists' => array($this, 'exists'), + 'replace_pattern' =>'([^a-z0-9_]+)|(^custom$)', + 'error' => 'The machine-readable name must be unique, and can only contain lowercase letters, numbers, and underscores. Additionally, it can not be the reserved word "custom".', ), '#disabled' => !$robot->isNew(), ); @@ -71,6 +114,31 @@ } /** + * Checks for an existing robot. + * + * @param string|int $entity_id + * The entity ID. + * @param array $element + * The form element. + * @param array $form_state + * The form state. + * + * @return bool + * TRUE if this format already exists, FALSE otherwise. + */ + public function exists($entity_id, array $element, array $form_state) { + // Use the query factory to build a new robot entity query. + $query = $this->entityQueryFactory->get('robot'); + + // Query the entity ID to see if its in use. + $result = $query->condition('id', $element['#field_prefix'] . $entity_id) + ->execute(); + + // We don't need to return the ID, only if it exists or not. + return (bool) $result; + } + + /** * Overrides Drupal\Core\Entity\EntityFormController::actions(). * * To set the submit button text, we need to override actions(). diff -u b/config_entity_example/lib/Drupal/config_entity_example/Tests/ConfigEntityExampleTest.php b/config_entity_example/lib/Drupal/config_entity_example/Tests/ConfigEntityExampleTest.php --- b/config_entity_example/lib/Drupal/config_entity_example/Tests/ConfigEntityExampleTest.php +++ b/config_entity_example/lib/Drupal/config_entity_example/Tests/ConfigEntityExampleTest.php @@ -31,7 +31,7 @@ * Various functional test of the Config Entity Example module. * * 1) Verify that the Marvin entity was created when the module was installed. - * + * * 2) Verify that permissions are applied to the various defined paths. * * 3) Verify that we can manage entities through the user interface. @@ -77,7 +77,7 @@ $this->drupalGet($unforbidden); $this->assertResponse(200, "Access granted to admin user for path: $unforbidden"); } - + // 3) Verify that we can manage entities through the user interface. // We still have the admin user logged in, so we'll create, update, and // delete an entity.