Пользовательские модули Drupal 8 - установка дополнительной конфигурации из файлов YML с помощью hook_update_N - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть пользовательский модуль, который устанавливает определенный набор конфигураций - все они хранятся в папке config/install, что означает, что они устанавливаются при установке модуля.

Конфигурация включает в себя тип контента, абзацы, режимы просмотра, режимы форм, хранилища полей и поля, прикрепленные как к типу контента, так и к абзацам и т. Д. Идея состоит в том, чтобы использовать этот модуль для установки «функции» (блог ) и использовать его на нескольких сайтах, а также предоставлять обновления и расширения, когда мы добавляем больше материалов для этой функции.

Поскольку после первоначальной установки вы не можете добавить больше настроек через папку config/install, я пытался найти способ импортировать дополнительные файлы конфигурации через ловушку обновления, и это тот, который работает:

<?php

use \Symfony\Component\Yaml\Yaml;

/**
 * Installs the file upload element
 */
function MODULE_NAME_update_8002() {

  // Is the flaw with this the fact that the order of loading configurations now
  // matters and is a little bit more difficult to deal with?
  // NOTE:  YES. If, for example, you comment out the installing of the
  // field_storage for the field_cb_file, but try to add the field_cb_file to
  // the paragraph type, the update is successful and no errors are thrown.
  // This is basically me trying to re-create the drupal configuration management
  // system, without the dependency checks, etc. What is the PROPER way of
  // importing additional configuration from a module through an update?
  //  FIXME:  

  $configs_to_install = [
    'paragraphs.paragraphs_type.cbsf_file_download',
    'field.storage.paragraph.field_cb_file',
    'field.field.paragraph.cbsf_file_download.field_cb_file',
    'field.field.paragraph.cbsf_file_download.field_cb_heading',
    'field.field.paragraph.cbsf_file_download.field_cb_icon',
    'field.field.paragraph.cbsf_file_download.field_cb_text',
    'core.entity_form_display.paragraph.cbsf_file_download.default',
    'core.entity_view_display.paragraph.cbsf_file_download.default',
  ];

  foreach ($configs_to_install as $config_to_install) {
    $path = drupal_get_path('module', 'MODULE_NAME') . '/config/update_8002/' . $config_to_install . '.yml';
    $content = file_get_contents($path);
    $parsed_yml = Yaml::parse($content);

    $active_storage = \Drupal::service('config.storage');
    $active_storage->write($config_to_install, $parsed_yml);
  }
}

однако у этого метода есть недостатки, так как это означает, что вы должны упорядочивать файлы конфигурации в правильном порядке, если они зависят друг от друга, и любые зависимости, присутствующие в файле конфигурации, не проверяются.

Есть ли способ использовать управление конфигурацией для правильного импорта конфигурации, таким же образом, как «перебирать файлы»? Или указать на папку, содержащую все файлы конфигурации и установить их?


РЕДАКТИРОВАТЬ : у этого метода есть и другие проблемы - даже если вы правильно упорядочили файлы с точки зрения зависимостей, таблицы базы данных не создаются. Конфигурация просто «записана» как есть, и никакая другая часть Drupal, похоже, не знает о том, что были созданы новые сущности, поэтому они не могут запускать какие-либо функции, которые в противном случае запускались бы, если бы вы создавали сущности через графический интерфейс Drupal. , Определенно не рекомендуемый способ передачи более сложной конфигурации.

1 Ответ

0 голосов
/ 11 сентября 2018

Я продвинулся на шаг вперед - есть способ использовать класс EntityTypeManager для создания / обновления конфигураций.


2 ссылки помогли мне в этом:

https://drupal.stackexchange.com/questions/164713/how-do-i-update-the-configuration-of-a-module

pwolanins ответ внизу предоставляет функцию, которая либо обновляет конфигурацию, если она существует, либо создает конфигурацию напрямую.

https://www.metaltoad.com/blog/programmatically-importing-drupal-8-field-configurations

код на этой странице дает более четкое представление о том, что происходит - для каждой конфигурации, которую вы хотите установить, вы запускаете файл YML через соответствующий менеджер хранилища, а затем создаете соответствующие конфигурации сущностей, которые создают все необходимых таблиц БД.


То, что я закончил, было:

Использовал слегка модифицированную версию кода pwolanins и создал общую функцию обновления конфигурации -

function _update_or_install_config( String $prefix, String $update_id, String $module) {
  $updated = [];
  $created = [];

  /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
  $config_manager = \Drupal::service('config.manager');
  $files = glob(drupal_get_path('module', $module) . '/config/update_' . $update_id. '/' . $prefix . '*.yml') ;
  foreach ($files as $file) {
    $raw = file_get_contents($file);
    $value = \Drupal\Component\Serialization\Yaml::decode($raw);
    if(!is_array($value)) {
      throw new \RuntimeException(sprintf('Invalid YAML file %s'), $file);
    }

    $type = $config_manager->getEntityTypeIdByName(basename($file));
    $entity_manager = $config_manager->getEntityManager();
    $definition = $entity_manager->getDefinition($type);
    $id_key = $definition->getKey('id');
    $id = $value[$id_key];

    /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $entity_storage */
    $entity_storage = $entity_manager->getStorage($type);
    $entity = $entity_storage->load($id);
    if ($entity) {
      $entity = $entity_storage->updateFromStorageRecord($entity, $value);
      $entity->save();
      $updated[] = $id;
    }
    else {
      $entity = $entity_storage->createFromStorageRecord($value);
      $entity->save();
      $created[] = $id;
    }
  }

  return [
    'udpated' => $updated,
    'created' => $created,
  ];
}

Я поместил все свои yml файлы в папку config/update_8002, затем использовал эту функцию для циклического перебора файлов конфигурации в функции hook_update_N:

function MODULE_NAME_update_8002() {

  $configs_to_install = [
    'paragraphs.paragraphs_type.cbsf_file_download',
    'core.entity_form_display.paragraph.cbsf_file_download.default',
    'core.entity_view_display.paragraph.cbsf_file_download.default',
    'field.storage.paragraph.field_cb_file',
    'field.field.paragraph.cbsf_file_download.field_cb_file',
    'field.field.paragraph.cbsf_file_download.field_cb_heading',
    'field.field.paragraph.cbsf_file_download.field_cb_icon',
    'field.field.paragraph.cbsf_file_download.field_cb_text',
  ];

  foreach ($configs_to_install as $config_to_install) {
    _update_or_install_config('paragraphs.paragraphs_type', '8002', 'MODULE_NAME');
    _update_or_install_config('field.storage.paragraph', '8002', 'MODULE_NAME');
    _update_or_install_config('field.field.paragraph', '8002', 'MODULE_NAME');
    _update_or_install_config('core.entity_view_display.paragraph', '8002', 'MODULE_NAME');
    _update_or_install_config('core.entity_form_display.paragraph', '8002', 'MODULE_NAME');
  }

}

Обратите внимание, что функция _update_or_install_config перебирает все конфиги в папке, которые соответствуют определенному менеджеру типов сущностей - таким образом, вы должны просто включить префикс в функцию и все файлы YML, которые импортируют конфигурацию того же самого тип будет включен.

...