/**
   * Tests simple IEF widget with different cardinality options.
   *
   * @throws \Exception
   */
  protected function testSimpleCardinalityOptions() {
    $this->drupalLogin($this->user);
    $cardinality_options = [
      1 => 1,
      2 => 2,
      FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED => 3,
    ];
    /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
    $field_storage = $this->fieldStorageConfigStorage->load('node.single');
    foreach ($cardinality_options as $cardinality => $limit) {
      $field_storage->setCardinality($cardinality);
      $field_storage->save();

      $this->drupalGet('node/add/ief_simple_single');

      $this->assertText('Single node', 'Inline entity field widget title found.');
      $this->assertText('Reference a single node.', 'Inline entity field description found.');

      $add_more_xpath = '//input[@data-drupal-selector="edit-single-add-more"]';
      if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
        $this->assertFieldByXPath($add_more_xpath, NULL, 'Add more button exists');
      }
      else {
        $this->assertNoFieldByXPath($add_more_xpath, NULL, 'Add more button does NOT exist');
      }

      $edit = ['title[0][value]' => 'Host node'];
      for ($item_number = 0; $item_number < $limit; $item_number++) {
        $edit["single[$item_number][inline_entity_form][title][0][value]"] = 'Child node nr.' . $item_number;
        if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
          $next_item_number = $item_number + 1;
          $this->assertNoFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does not appear before 'Add More' clicked");
          if ($item_number < $limit - 1) {
            $this->drupalPostAjaxForm(NULL, $edit, 'single_add_more');
            // This needed because the first time "add another item" is clicked it does not work
            // see https://www.drupal.org/node/2664626
            if ($item_number == 0) {
              $this->drupalPostAjaxForm(NULL, $edit, 'single_add_more');
            }

            $this->assertFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does  appear after 'Add More' clicked");
          }

        }
      }
      $this->drupalPostForm(NULL, $edit, t('Save'));

      for ($item_number = 0; $item_number < $limit; $item_number++) {
        $this->assertText('Child node nr.' . $item_number, 'Label of referenced entity found.');
      }
    }
  }
示例#2
0
 /**
  * @covers ::delete
  * @covers ::doDelete
  */
 public function testDeleteNothing()
 {
     $this->moduleHandler->expects($this->never())->method($this->anything());
     $this->configFactory->expects($this->never())->method('get');
     $this->cacheTagsInvalidator->expects($this->never())->method('invalidateTags');
     $this->entityStorage->delete(array());
 }
 /**
  * Constructs a FieldStorageConfigStorage object.
  *
  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
  *   The entity type definition.
  * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
  *   The config factory service.
  * @param \Drupal\Core\Config\StorageInterface $config_storage
  *   The config storage service.
  * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
  *   The UUID service.
  * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
  *   The language manager.
  * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
  *   The entity manager.
  * @param \Drupal\Core\Extension\ModuleHandler $module_handler
  *   The module handler.
  * @param \Drupal\Core\State\StateInterface $state
  *   The state key value store.
  */
 public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, ModuleHandler $module_handler, StateInterface $state)
 {
     parent::__construct($entity_type, $config_factory, $config_storage, $uuid_service, $language_manager);
     $this->entityManager = $entity_manager;
     $this->moduleHandler = $module_handler;
     $this->state = $state;
 }
 /**
  * Tests configuration renaming.
  */
 public function testConfigurationRename()
 {
     $content_type = entity_create('node_type', array('type' => Unicode::strtolower($this->randomName(16)), 'name' => $this->randomName()));
     $content_type->save();
     $staged_type = $content_type->type;
     $active = $this->container->get('config.storage');
     $staging = $this->container->get('config.storage.staging');
     $config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id();
     // Emulate a staging operation.
     $this->copyConfig($active, $staging);
     // Change the machine name of the content type.
     $content_type->type = Unicode::strtolower($this->randomName(8));
     $content_type->save();
     $active_type = $content_type->type;
     $renamed_config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id();
     $this->assertTrue($active->exists($renamed_config_name), 'The content type has the new name in the active store.');
     $this->assertFalse($active->exists($config_name), "The content type's old name does not exist active store.");
     $this->configImporter()->reset();
     $this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('create')), 'There are no configuration items to create.');
     $this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('delete')), 'There are no configuration items to delete.');
     $this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('update')), 'There are no configuration items to update.');
     // We expect that changing the machine name of the content type will
     // rename five configuration entities: the node type, the body field
     // instance, two entity form displays, and the entity view display.
     // @see \Drupal\node\Entity\NodeType::postSave()
     $expected = array('node.type.' . $active_type . '::node.type.' . $staged_type, 'entity.form_display.node.' . $active_type . '.default::entity.form_display.node.' . $staged_type . '.default', 'entity.view_display.node.' . $active_type . '.default::entity.view_display.node.' . $staged_type . '.default', 'entity.view_display.node.' . $active_type . '.teaser::entity.view_display.node.' . $staged_type . '.teaser', 'field.instance.node.' . $active_type . '.body::field.instance.node.' . $staged_type . '.body');
     $renames = $this->configImporter()->getUnprocessedConfiguration('rename');
     $this->assertIdentical($expected, $renames);
     $this->drupalGet('admin/config/development/configuration');
     foreach ($expected as $rename) {
         $names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename);
         $this->assertText(String::format('!source_name to !target_name', array('!source_name' => $names['old_name'], '!target_name' => $names['new_name'])));
         // Test that the diff link is present for each renamed item.
         $href = \Drupal::urlGenerator()->getPathFromRoute('config.diff', array('source_name' => $names['old_name'], 'target_name' => $names['new_name']));
         $this->assertLinkByHref($href);
         $hrefs[$rename] = $href;
     }
     // Ensure that the diff works for each renamed item.
     foreach ($hrefs as $rename => $href) {
         $this->drupalGet($href);
         $names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename);
         $config_entity_type = \Drupal::service('config.manager')->getEntityTypeIdByName($names['old_name']);
         $entity_type = \Drupal::entityManager()->getDefinition($config_entity_type);
         $old_id = ConfigEntityStorage::getIDFromConfigName($names['old_name'], $entity_type->getConfigPrefix());
         $new_id = ConfigEntityStorage::getIDFromConfigName($names['new_name'], $entity_type->getConfigPrefix());
         // Because table columns can be on multiple lines, need to assert a regex
         // pattern rather than normal text.
         $id_key = $entity_type->getKey('id');
         $text = "{$id_key}: {$old_id}";
         $this->assertTextPattern('/\\-\\s+' . preg_quote($text, '/') . '/', "'-{$text}' found.");
         $text = "{$id_key}: {$new_id}";
         $this->assertTextPattern('/\\+\\s+' . preg_quote($text, '/') . '/', "'+{$text}' found.");
     }
     // Run the import.
     $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all'));
     $this->assertText(t('There are no configuration changes.'));
     $this->assertFalse(entity_load('node_type', $active_type), 'The content no longer exists with the old name.');
     $content_type = entity_load('node_type', $staged_type);
     $this->assertIdentical($staged_type, $content_type->type);
 }
示例#5
0
 /**
  * {@inheritdoc}
  */
 protected function mapToStorageRecord(EntityInterface $entity)
 {
     $record = parent::mapToStorageRecord($entity);
     $class = $this->fieldTypeManager->getPluginClass($record['field_type']);
     $record['settings'] = $class::fieldSettingsToConfigData($record['settings']);
     return $record;
 }
 /**
  * {@inheritdoc}
  */
 protected function doDelete($entities)
 {
     // ZZ is the fallback address format and it must always be present.
     if (array_key_exists('ZZ', $entities) && current($entities)->isUninstalling() === FALSE) {
         throw new EntityStorageException("The 'ZZ' address format can't be deleted.");
     }
     parent::doDelete($entities);
 }
示例#7
0
 /**
  * {@inheritdoc}
  */
 public function loadMultiple(array $ids = NULL)
 {
     /** @var \Drupal\migrate\Entity\MigrationInterface[] $migrations */
     $migrations = parent::loadMultiple($ids);
     foreach ($migrations as $migration) {
         $migration->set('migration_dependencies', $this->expandDependencies($migration->getMigrationDependencies()));
     }
     return $migrations;
 }
 /**
  * {@inheritdoc}
  */
 public function importDelete($name, Config $new_config, Config $old_config)
 {
     // If the field has been deleted in the same import, the instance will be
     // deleted by then, and there is nothing left to do. Just return TRUE so
     // that the file does not get written to active store.
     if (!$old_config->get()) {
         return TRUE;
     }
     return parent::importDelete($name, $new_config, $old_config);
 }
 /**
  * {@inheritdoc}
  */
 protected function mapFromStorageRecords(array $records)
 {
     $entities = parent::mapFromStorageRecords($records);
     $prefix = $this->entityTypeManager->getDefinition('moderation_state')->getConfigPrefix();
     /* @var \Drupal\workbench_moderation\ModerationStateTransitionInterface $entity */
     foreach ($entities as &$entity) {
         $entity->setModerationStateConfigPrefix($prefix);
     }
     reset($entities);
     return $entities;
 }
 /**
  * {@inheritdoc}
  */
 protected function doDelete($entities)
 {
     // ZZ is the fallback address format and it must always be present.
     if (isset($entities['ZZ'])) {
         $entity = $entities['ZZ'];
         if (!$entity->isUninstalling() && !$entity->isSyncing()) {
             throw new EntityStorageException("The 'ZZ' address format can't be deleted.");
         }
     }
     parent::doDelete($entities);
 }
 /**
  * @covers ::loadByEntityTypeBundle
  *
  * @dataProvider providerLoadByEntityTypeBundle
  */
 public function testLoadByEntityTypeBundle($config_id, ContentLanguageSettings $existing_config = NULL, $expected_langcode, $expected_language_alterable)
 {
     list($type, $bundle) = explode('.', $config_id);
     $nullConfig = new ContentLanguageSettings(array('target_entity_type_id' => $type, 'target_bundle' => $bundle), 'language_content_settings');
     $this->configEntityStorageInterface->expects($this->any())->method('load')->with($config_id)->will($this->returnValue($existing_config));
     $this->configEntityStorageInterface->expects($this->any())->method('create')->will($this->returnValue($nullConfig));
     $this->entityManager->expects($this->any())->method('getStorage')->with('language_content_settings')->will($this->returnValue($this->configEntityStorageInterface));
     $this->entityManager->expects($this->any())->method('getEntityTypeFromClass')->with('Drupal\\language\\Entity\\ContentLanguageSettings')->willReturn('language_content_settings');
     $config = ContentLanguageSettings::loadByEntityTypeBundle($type, $bundle);
     $this->assertSame($expected_langcode, $config->getDefaultLangcode());
     $this->assertSame($expected_language_alterable, $config->isLanguageAlterable());
 }
示例#12
0
 /**
  * {@inheritdoc}
  */
 public function loadMultiple(array $ids = NULL)
 {
     if ($ids) {
         $ids = $this->getVariantIds($ids);
     }
     /** @var \Drupal\migrate\Entity\MigrationInterface[] $migrations */
     $migrations = parent::loadMultiple($ids);
     foreach ($migrations as $migration) {
         $dependencies = array_map([$this, 'getVariantIds'], $migration->getMigrationDependencies());
         $migration->set('migration_dependencies', $dependencies);
     }
     // Build an array of dependencies and set the order of the migrations.
     return $this->buildDependencyMigration($migrations, []);
 }
 /**
  * Ensures bundles that will be deleted are not in use.
  *
  * @param \Drupal\Core\Config\ConfigImporterEvent $event
  *   The config import event.
  */
 public function onConfigImporterValidate(ConfigImporterEvent $event)
 {
     foreach ($event->getChangelist('delete') as $config_name) {
         // Get the config entity type ID. This also ensure we are dealing with a
         // configuration entity.
         if ($entity_type_id = $this->configManager->getEntityTypeIdByName($config_name)) {
             $entity_type = $this->entityManager->getDefinition($entity_type_id);
             // Does this entity type define a bundle of another entity type.
             if ($bundle_of = $entity_type->getBundleOf()) {
                 // Work out if there are entities with this bundle.
                 $bundle_of_entity_type = $this->entityManager->getDefinition($bundle_of);
                 $bundle_id = ConfigEntityStorage::getIDFromConfigName($config_name, $entity_type->getConfigPrefix());
                 $entity_query = $this->entityManager->getStorage($bundle_of)->getQuery();
                 $entity_ids = $entity_query->condition($bundle_of_entity_type->getKey('bundle'), $bundle_id)->accessCheck(FALSE)->range(0, 1)->execute();
                 if (!empty($entity_ids)) {
                     $entity = $this->entityManager->getStorage($entity_type_id)->load($bundle_id);
                     $event->getConfigImporter()->logError($this->t('Entities exist of type %entity_type and %bundle_label %bundle. These entities need to be deleted before importing.', array('%entity_type' => $bundle_of_entity_type->getLabel(), '%bundle_label' => $bundle_of_entity_type->getBundleLabel(), '%bundle' => $entity->label())));
                 }
             }
         }
     }
 }
示例#14
0
 /**
  * Constructs a GradeScaleStorageController object.
  *
  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_info
  *   The entity info for the entity type.
  * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
  *   The config factory service.
  * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
  *   The UUID service.
  * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
  *   The module handler.
  * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
  *   The language manager.
  */
 public function __construct(EntityTypeInterface $entity_info, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager)
 {
     parent::__construct($entity_info, $config_factory, $uuid_service, $language_manager);
     $this->moduleHandler = $module_handler;
 }
示例#15
0
 /**
  * Overrides \Drupal\Core\Config\Entity\ConfigEntityStorage::importDelete().
  */
 public function importDelete($name, Config $new_config, Config $old_config)
 {
     // Set a global value we can check in test code.
     $GLOBALS['hook_config_import'] = __METHOD__;
     return parent::importDelete($name, $new_config, $old_config);
 }
示例#16
0
 /**
  * Tests the display related functions like getDisplaysList().
  */
 protected function displayMethodTests()
 {
     // Enable the system module so _l() can work using url_alias table.
     $this->installSchema('system', 'url_alias');
     $config['display'] = array('page_1' => array('display_options' => array('path' => 'test'), 'display_plugin' => 'page', 'id' => 'page_2', 'display_title' => 'Page 1', 'position' => 1), 'feed_1' => array('display_options' => array('path' => 'test.xml'), 'display_plugin' => 'feed', 'id' => 'feed', 'display_title' => 'Feed', 'position' => 2), 'page_2' => array('display_options' => array('path' => 'test/%/extra'), 'display_plugin' => 'page', 'id' => 'page_2', 'display_title' => 'Page 2', 'position' => 3));
     $view = $this->controller->create($config);
     // Tests Drupal\views\Entity\View::addDisplay()
     $view = $this->controller->create(array());
     $random_title = $this->randomMachineName();
     $id = $view->addDisplay('page', $random_title);
     $this->assertEqual($id, 'page_1', format_string('Make sure the first display (%id_new) has the expected ID (%id)', array('%id_new' => $id, '%id' => 'page_1')));
     $display = $view->get('display');
     $this->assertEqual($display[$id]['display_title'], $random_title);
     $random_title = $this->randomMachineName();
     $id = $view->addDisplay('page', $random_title);
     $display = $view->get('display');
     $this->assertEqual($id, 'page_2', format_string('Make sure the second display (%id_new) has the expected ID (%id)', array('%id_new' => $id, '%id' => 'page_2')));
     $this->assertEqual($display[$id]['display_title'], $random_title);
     $id = $view->addDisplay('page');
     $display = $view->get('display');
     $this->assertEqual($display[$id]['display_title'], 'Page 3');
     // Ensure the 'default' display always has position zero, regardless of when
     // it was set relative to other displays. Even if the 'default' display
     // exists, adding it again will overwrite it, which is asserted with the new
     // title.
     $view->addDisplay('default', $random_title);
     $displays = $view->get('display');
     $this->assertEqual($displays['default']['display_title'], $random_title, 'Default display is defined with the new title');
     $this->assertEqual($displays['default']['position'], 0, 'Default displays are always in position zero');
     // Tests Drupal\views\Entity\View::generateDisplayId(). Since
     // generateDisplayId() is protected, we have to use reflection to unit-test
     // it.
     $view = $this->controller->create(array());
     $ref_generate_display_id = new \ReflectionMethod($view, 'generateDisplayId');
     $ref_generate_display_id->setAccessible(TRUE);
     $this->assertEqual($ref_generate_display_id->invoke($view, 'default'), 'default', 'The plugin ID for default is always default.');
     $this->assertEqual($ref_generate_display_id->invoke($view, 'feed'), 'feed_1', 'The generated ID for the first instance of a plugin type should have an suffix of _1.');
     $view->addDisplay('feed', 'feed title');
     $this->assertEqual($ref_generate_display_id->invoke($view, 'feed'), 'feed_2', 'The generated ID for the first instance of a plugin type should have an suffix of _2.');
     // Tests item related methods().
     $view = $this->controller->create(array('base_table' => 'views_test_data'));
     $view->addDisplay('default');
     $view = $view->getExecutable();
     $display_id = 'default';
     $expected_items = array();
     // Tests addHandler with getItem.
     // Therefore add one item without any options and one item with some
     // options.
     $id1 = $view->addHandler($display_id, 'field', 'views_test_data', 'id');
     $item1 = $view->getHandler($display_id, 'field', 'id');
     $expected_items[$id1] = $expected_item = array('id' => 'id', 'table' => 'views_test_data', 'field' => 'id', 'plugin_id' => 'numeric');
     $this->assertEqual($item1, $expected_item);
     $options = array('alter' => array('text' => $this->randomMachineName()));
     $id2 = $view->addHandler($display_id, 'field', 'views_test_data', 'name', $options);
     $item2 = $view->getHandler($display_id, 'field', 'name');
     $expected_items[$id2] = $expected_item = array('id' => 'name', 'table' => 'views_test_data', 'field' => 'name', 'plugin_id' => 'standard') + $options;
     $this->assertEqual($item2, $expected_item);
     // Tests the expected fields from the previous additions.
     $this->assertEqual($view->getHandlers('field', $display_id), $expected_items);
     // Alter an existing item via setItem and check the result via getItem
     // and getItems.
     $item = array('alter' => array('text' => $this->randomMachineName())) + $item1;
     $expected_items[$id1] = $item;
     $view->setHandler($display_id, 'field', $id1, $item);
     $this->assertEqual($view->getHandler($display_id, 'field', 'id'), $item);
     $this->assertEqual($view->getHandlers('field', $display_id), $expected_items);
     // Test removeItem method.
     unset($expected_items[$id2]);
     $view->removeHandler($display_id, 'field', $id2);
     $this->assertEqual($view->getHandlers('field', $display_id), $expected_items);
 }
 /**
  * Gets the list of fields to purge before configuration synchronization.
  *
  * If, during a configuration synchronization, a field is being deleted and
  * the module that provides the field type is being uninstalled then the field
  * data must be purged before the module is uninstalled. Also, if deleted
  * fields exist whose field types are provided by modules that are being
  * uninstalled their data need to be purged too.
  *
  * @param array $extensions
  *   The list of extensions that will be enabled after the configuration
  *   synchronization has finished.
  * @param array $deletes
  *   The configuration that will be deleted by the configuration
  *   synchronization.
  *
  * @return \Drupal\field\Entity\FieldStorageConfig[]
  *   An array of field storages that need purging before configuration can be
  *   synchronized.
  */
 public static function getFieldStoragesToPurge(array $extensions, array $deletes)
 {
     $providers = array_keys($extensions['module']);
     $providers[] = 'core';
     $storages_to_delete = array();
     // Gather fields that will be deleted during configuration synchronization
     // where the module that provides the field type is also being uninstalled.
     $field_storage_ids = array();
     foreach ($deletes as $config_name) {
         $field_storage_config_prefix = \Drupal::entityManager()->getDefinition('field_storage_config')->getConfigPrefix();
         if (strpos($config_name, $field_storage_config_prefix . '.') === 0) {
             $field_storage_ids[] = ConfigEntityStorage::getIDFromConfigName($config_name, $field_storage_config_prefix);
         }
     }
     if (!empty($field_storage_ids)) {
         $field_storages = \Drupal::entityQuery('field_storage_config')->condition('id', $field_storage_ids, 'IN')->condition('module', $providers, 'NOT IN')->execute();
         if (!empty($field_storages)) {
             $storages_to_delete = FieldStorageConfig::loadMultiple($field_storages);
         }
     }
     // Gather deleted fields from modules that are being uninstalled.
     /** @var \Drupal\field\FieldStorageConfigInterface[] $field_storages */
     $field_storages = entity_load_multiple_by_properties('field_storage_config', array('deleted' => TRUE, 'include_deleted' => TRUE));
     foreach ($field_storages as $field_storage) {
         if (!in_array($field_storage->getTypeProvider(), $providers)) {
             $storages_to_delete[$field_storage->id()] = $field_storage;
         }
     }
     return $storages_to_delete;
 }
 /**
  * {@inheritdoc}
  */
 public function delete(array $entities)
 {
     // After deleting a set of reaction rules, sometimes we may need to rebuild
     // the container, to clean it up, so that the generic subscriber is not
     // registered in the container for the rule events which we do not use
     // anymore. So we do that if there is any change in the registered events,
     // after the reaction rules are deleted.
     $events_before = $this->getRegisteredEvents();
     $return = parent::delete($entities);
     $events_after = $this->getRegisteredEvents();
     // Update the state of registered events and rebuild the container.
     if ($events_before != $events_after) {
         $this->stateService->set('rules.registered_events', $events_after);
         $this->drupalKernel->rebuildContainer();
     }
     return $return;
 }
示例#19
0
 /**
  * {@inheritdoc}
  */
 public function resetCache(array $ids = NULL)
 {
     drupal_static_reset('taxonomy_vocabulary_get_names');
     parent::resetCache($ids);
 }
示例#20
0
 /**
  * {@inheritdoc}
  */
 public function delete(array $entities)
 {
     $return = parent::delete($entities);
     // Update the state of registered events.
     // @todo Should we trigger a container rebuild here as well? Might be a bit
     // expensive on every delete?
     $this->stateService->set('rules.registered_events', $this->getRegisteredEvents());
     return $return;
 }
示例#21
0
 /**
  * {@inheritdoc}
  */
 public function delete(array $entities)
 {
     $return = parent::delete($entities);
     return $return;
 }