<?php /** * @file * Install, update and uninstall for Configuration of all common WCMS. */ use Drupal\Core\Config\FileStorage; use Drupal\field\Entity\FieldConfig; use Drupal\node\Entity\Node; use Drupal\taxonomy\Entity\Term; use Drupal\user\Entity\Role; use Drupal\uw_cfg_common\UwPermissions\UwPermissions; use Drupal\uw_cfg_common\UwRoles\UwRoles; use Drupal\webform\WebformInterface; use Symfony\Component\Yaml\Yaml; /** * Implements hook_install(). */ function uw_cfg_common_install() { // ISTWCMS-5865: this the attempt to fix features for our build. // Moving the actual installing of workflows to here, so that // we can include workflows as a dependency in our modules and // that it will allow new site installs. $name = 'workflows.workflow.uw_workflow'; $path = \Drupal::service('extension.list.module')->getPath('uw_cfg_common') . '/config/custom/'; $source = new FileStorage($path); $active_storage = \Drupal::service('config.storage'); $active_storage->write($name, $source->read($name)); // Get the role ids for UW roles. $uw_rids = UwRoles::getUwRoleIds(); // Step through each of the rids and create // role and set permissions. foreach ($uw_rids as $uw_rid) { // Create the role. $role = Role::create( [ 'id' => $uw_rid, 'label' => UwRoles::getUwRoleLabel($uw_rid), ] ); $role->save(); // Get the info about the role. $uw_role = UwRoles::getUwRole($uw_rid); // Set the permissions for the role. UwRoles::setUwPermissions($uw_role); } // Get the role ids for Drupal roles. $drupal_rids = UwRoles::getDrupalRoleIds(); // Step through each of the Drupal roles and // set the permissions. foreach ($drupal_rids as $drupal_rid) { // Get the info about the role. $uw_role = UwRoles::getUwRole($drupal_rid); // Set the permissions for the role. UwRoles::setUwPermissions($uw_role); } // Build the access permissions array. $module_handler = \Drupal::service('module_handler'); $module_path = $module_handler->getModule('uw_cfg_common')->getPath(); $permissions_to_process = Yaml::parseFile($module_path . '/src/UwRoles/access_content_permissions.yml'); UwPermissions::grantRevoke($permissions_to_process, 'grant'); // Add terms to the vocabulary 'uw_vocab_audience'. $terms = [ 'Current students' => [ 'Current undergraduate students', 'Current graduate students', ], 'Future students' => [ 'Future undergraduate students', 'Future graduate students', ], 'Faculty' => 'Faculty', 'Staff' => 'Staff', 'Alumni' => 'Alumni', 'Parents' => 'Parents', 'Donors | Friends | Supporters' => 'Donors | Friends | Supporters', 'Employers' => 'Employers', 'International' => 'International', 'Media' => 'Media', ]; $weight = 0; foreach ($terms as $key => $term) { if (is_array($term)) { $parent = _uw_cfg_common_create_term($key, 'uw_vocab_audience', $weight, []); $childweight = 0; foreach ($term as $child) { _uw_cfg_common_create_term($child, 'uw_vocab_audience', $childweight, [$parent]); $childweight++; } } else { _uw_cfg_common_create_term($term, 'uw_vocab_audience', $weight, []); } $weight++; } } /** * @file * Contains various helper functions. */ /** * Helper function to create a taxonomy term programmatically. * * @code * // Create top level term * $term_id = _nodemaker_term_create('My Term', 'my_vocab', 0, []); * * // Create term with parent term with an id of 999 * $term_id = _nodemaker_term_create('My Term', 'my_vocab', 0, [999]); * @endcode * * @param string $taxonomy_name * - Term Name. * @param string $vocab_machine_name * - System id of the vocabulary term will be added to. * @param string|int $weight * - Taxonomy term weight. * @param array $parent_tid * - Array of term ids to be assigned as parent. * * @return int|null * - Returns the term id of the created term on success, null on failure. * * @throws \Drupal\Core\Entity\EntityStorageException */ function _uw_cfg_common_create_term($taxonomy_name, $vocab_machine_name, $weight, array $parent_tid = []) { // Create the taxonomy term. $new_term = Term::create([ 'name' => $taxonomy_name, 'vid' => $vocab_machine_name, 'parent' => $parent_tid, 'weight' => $weight, ]); // Save the taxonomy term. $new_term->save(); // Return the taxonomy term id. return $new_term->id(); } /** * Implements hook_update_dependencies(). */ function uw_cfg_common_update_dependencies() { $dependencies['uw_cfg_common'][8103] = [ 'uw_sites_all' => 8105, ]; $dependencies['uw_cfg_common'][9108] = [ 'uw_ct_service' => 9101, ]; return $dependencies; } /** * Implements hook_update_N(). */ /** * Update listing blocks items per page when needed. * * For listing blocks items per page, when default settings were used, * change to the original default number of items. */ function uw_cfg_common_update_8101() { // Block ids that need to be changed, and what the original default was. // For some reason, we didn't originally use the same number for everything. $block_ids = [ 'views_block:uw_view_blogs-blogs_listing_block' => 5, 'views_block:uw_view_events-events_listing_block' => 10, 'views_block:uw_view_news_items-news_items_listing_block' => 10, ]; // Load all the nodes. $nodes = Node::loadMultiple(); // Step through each node and set any that were using the default setting // to the number that was the default before this change. foreach ($nodes as $node) { // Flag to save the node, have this to save processing // time if we don't need to save the node after the checks. $save_node_flag = FALSE; // Load the layout and sections. $layout = $node->get('layout_builder__layout'); $sections = $layout->getSections(); // Step through each of the sections. foreach ($sections as $section) { // Load the components for the section. $components = $section->getComponents(); // Step through each of the components. foreach ($components as $component) { // If this component is one that needs to be changed, // then check for setting and change if required. if (in_array($component->getPluginId(), array_keys($block_ids))) { // Load the config for the block. $configurations = $component->get('configuration'); // If the config is set to "none", it needs to be changed to // be set to the number that was the old default value. if ($configurations['items_per_page'] == 'none') { // Change the config and save the component. $configurations['items_per_page'] = $block_ids[$component->getPluginId()]; $component->setConfiguration($configurations); // Set the save node flag so that we know to // save this node as the last step in the loop. $save_node_flag = TRUE; } } } // If we need to save the node, then save it. if ($save_node_flag) { $node->save(); } } // Load all the revisions for the node. $vids = \Drupal::service('entity_type.manager')->getStorage('node')->revisionIds($node); // Step through each revision, and check if we have to // change the settings for the listing blocks. foreach ($vids as $vid) { // Flag to see if we have to save the revision. $save_revision_flag = FALSE; // Load the revision node. $revision_node = \Drupal::service('entity_type.manager')->getStorage('node')->loadRevision($vid); // Comments from here down are the same as above. $layout = $revision_node->get('layout_builder__layout'); $sections = $layout->getSections(); foreach ($sections as $section) { $components = $section->getComponents(); foreach ($components as $component) { if (in_array($component->getPluginId(), $block_ids)) { $configurations = $component->get('configuration'); if ( $configurations['items_per_page'] == 'none' || $configurations['items_per_page'] == '5' ) { $configurations['items_per_page'] = '3'; $component->setConfiguration($configurations); $save_revision_flag = TRUE; } } } } if ($save_revision_flag) { $revision_node->save(); } } } } /** * Set draggable views permissions, since cd-update doesn't do it reliably. */ function uw_cfg_common_update_8102() { $roles = [ 'uw_role_content_author', 'uw_role_content_editor', 'uw_role_form_editor', 'uw_role_form_results_access', 'uw_role_site_manager', 'uw_role_site_owner', ]; foreach ($roles as $role_name) { $role_object = Role::load($role_name); $role_object->grantPermission('access draggableviews'); $role_object->save(); } } /** * Load config and assigns permissions to roles. * * Load quick_node_clone config. */ function uw_cfg_common_update_8103() { // Load config that is not being set properly by config distro update. $module_path = \Drupal::service('extension.list.module')->getPath('uw_cfg_common'); $config_path = $module_path . '/config/install'; $source = new FileStorage($config_path); $config_storage = \Drupal::service('config.storage'); $config_storage->write('quick_node_clone.settings', $source->read('quick_node_clone.settings')); // List of permissions needed to be applied to roles. $permissions = [ 'clone uw_ct_blog content', 'clone uw_ct_catalog_item content', 'clone uw_ct_contact content', 'clone uw_ct_event content', 'clone uw_ct_news_item content', 'clone uw_ct_profile content', 'clone uw_ct_sidebar content', 'clone uw_ct_web_page content', ]; // Roles that require updated permissions. $role_ids = [ 'uw_role_site_manager', 'uw_role_content_editor', 'uw_role_content_author', ]; $roles = Role::loadMultiple($role_ids); // Grant all all roles. foreach ($permissions as $permission) { $roles['uw_role_site_manager']->grantPermission($permission); $roles['uw_role_content_editor']->grantPermission($permission); $roles['uw_role_content_author']->grantPermission($permission); } // Save role with new permissions. $roles['uw_role_site_manager']->save(); $roles['uw_role_content_editor']->save(); $roles['uw_role_content_author']->save(); } /** * Give default access to Webforms that have no access to create submissions. */ function uw_cfg_common_update_8104() { $counter = 0; $webforms = \Drupal::entityTypeManager()->getStorage('webform')->loadMultiple(); foreach ($webforms as $webform) { $access = $webform->getAccessRules(); if (empty($access['create']['roles'])) { $access['create']['roles'] = [ 'anonymous', 'authenticated', ]; $webform->setAccessRules($access); $webform->save(); $counter++; } } return t('Set default access for @counter Webforms.', ['@counter' => $counter]); } /** * Update the fields required for new media section. */ function uw_cfg_common_update_9101() { // The content types to get updated. $node_types = [ 'uw_ct_blog', 'uw_ct_event', 'uw_ct_news_item', ]; // We need to a feature revert first, so tha the fields for // type of media are created. // Reverting uw_cfg_common first so that the fields get created. \Drupal::service('uw_cfg_common.features')->import(['uw_cfg_common']); // Revert the rest of the content types. \Drupal::service('uw_cfg_common.features')->import($node_types); // Step through each of the content types and update the field. foreach ($node_types as $node_type) { // Get all the nids of the content type. $query = \Drupal::service('entity_type.manager')->getStorage('node')->getQuery(); $nids = $query ->condition('type', $node_type) ->accessCheck(FALSE) ->execute(); // Step through each of the nids, get the node and check // if we have to update the field. foreach ($nids as $nid) { // Load the node. $node = \Drupal::service('entity_type.manager')->getStorage('node')->load($nid); // If there is a hero image, update the type of media field, // then save the node. if ($node->field_uw_hero_image->entity) { $node->set("field_uw_type_of_media", 'image'); $node->save(); } } } } /** * Set all Webforms to use the access denied page. */ function uw_cfg_common_update_9102() { $webforms = \Drupal::entityTypeManager()->getStorage('webform')->loadMultiple(); foreach ($webforms as $webform) { // This is set as the default in uw_cfg_common_webform_create(). $webform->setSetting('form_access_denied', WebformInterface::ACCESS_DENIED_PAGE); $webform->save(); } } /** * Add Private content viewer role for the existing site. */ function uw_cfg_common_update_9103() { Role::create([ 'id' => 'uw_role_private_content_viewer', 'label' => 'Private content viewer', ])->save(); } /** * Removes missing blocks from temp storage and saved nodes (revisions too). */ function uw_cfg_common_update_9104(&$sandbox) { $service = \Drupal::service('uw_cfg_common.missing_blocks'); $service->removeMissingBlocksFromUnsaved(); $service->removeMissingBlocksFromSaved(); } /** * Feature revert for workflows. */ function uw_cfg_common_update_9105(&$sandbox) { $name = 'workflows.workflow.uw_workflow'; $path = \Drupal::service('extension.list.module')->getPath('uw_cfg_common') . '/config/custom/'; $source = new FileStorage($path); $active_storage = \Drupal::service('config.storage'); $active_storage->write($name, $source->read($name)); } /** * Add new fields for banners above. */ function uw_cfg_common_update_9106(&$sandbox) { // The database service. $database = \Drupal::database(); // The tables to be used for fields to get and remove. $tables = [ 'node__field_uw_type_of_media', 'node_revision__field_uw_type_of_media', 'node__field_uw_hero_image', 'node_revision__field_uw_hero_image', ]; // Setting up an empty array so that we do not get // undefined index or unknown variable error. $node_data = []; // Step through each of the tables and get the data, // then truncate them. We need to truncate the table // so that we are able to modify the fields, if there // is data in these tables, Drupal throws an error about // data already existing in the fields. We will insert // the data back into the tables after everything is // completed. foreach ($tables as $table) { // Get the rows in the table. $values = $database->select($table, 'n') ->fields('n') ->execute() ->fetchAll(); // Step through each of the rows and add to variable. foreach ($values as $value) { // Add to the variable and cast to an array so that // we are not using an object, just makes it easier // to work with when inserting these rows back // into the database. $node_data[$table][] = (array) $value; } // Truncate the table. $database->truncate($table)->execute(); } // The content types that are not getting any changes. $cts_not_to_install = [ 'uw_ct_sidebar', 'uw_ct_site_footer', 'uw_ct_expand_collapse_group', ]; // The content types with media already in it (hero image). $cts_with_media = [ 'uw_ct_blog', 'uw_ct_event', 'uw_ct_news_item', ]; // Get all the node types. $node_types = \Drupal::entityTypeManager()->getStorage('node_type')->loadMultiple(); // Step through each node type and get the path to // the module and the machine name. foreach ($node_types as $node_type) { // Get the id from the node type. $id = $node_type->id(); // Ensure we are only getting the node type // that need updating. if (!in_array($id, $cts_not_to_install)) { // Catalogs and opportunities have different paths // and ids, so setup the content types array with // the correct info. if ($id == 'uw_ct_catalog_item') { $content_types['uw_ct_catalog'] = $id; } elseif ($id == 'uw_ct_opportunity') { $content_types['uw_ct_opportunities'] = $id; } else { $content_types[$id] = $id; } } } // Get the type of media field that we need to udpate. $type_of_media = current(\Drupal::entityTypeManager()->getStorage('field_storage_config')->loadByProperties(['id' => 'node.field_uw_type_of_media'])); // Get the type of media settings. $settings = $type_of_media->getSettings(); // Update the settings to remove the allowed values and // add the allowed values function. $settings['allowed_values'] = []; $settings['allowed_values_function'] = '_uw_cfg_common_allowed_media_types'; // Set the update settings. $type_of_media->setSettings($settings); // Save the field. $type_of_media->save(); // The names of the fields we need to install. $names = [ 'field.storage.node.field_uw_banner', 'field.storage.node.field_uw_media_width', 'field.storage.node.field_uw_slide_speed', 'field.storage.node.field_uw_transition_speed', 'field.storage.node.field_uw_autoplay', 'field.storage.node.field_uw_text_overlay_style', ]; // Get the path to cfg common config install directory. $path = \Drupal::service('extension.list.module')->getPath('uw_cfg_common') . '/config/install/'; $config_dir = new FileStorage($path); // Step through each of the field names and install them. foreach ($names as $name) { // Get the config from the yml file into an array. $config_record = $config_dir->read($name); // Get the entity type. $entity_type = \Drupal::service('config.manager')->getEntityTypeIdByName($name); // Get the storage. $storage = \Drupal::entityTypeManager()->getStorage($entity_type); // Create the new field from the converted yml. $field = $storage->createFromStorageRecord($config_record); // Save the new field. $field->save(); } // Step through each of the content types and install the fields, // and also setup default values for the fields. foreach ($content_types as $path => $id) { // Get the path to the content type. $path = \Drupal::service('extension.list.module')->getPath($path) . '/config/install/'; $config_dir = new FileStorage($path); // The names of the fields to install. $names = [ 'field.field.node.' . $id . '.field_uw_banner', 'field.field.node.' . $id . '.field_uw_type_of_media', 'field.field.node.' . $id . '.field_uw_media_width', 'field.field.node.' . $id . '.field_uw_slide_speed', 'field.field.node.' . $id . '.field_uw_autoplay', 'field.field.node.' . $id . '.field_uw_text_overlay_style', 'field.field.node.' . $id . '.field_uw_transition_speed', ]; // Step through each of the fields and install them. foreach ($names as $name) { // Get the config from the yml into an array. $config_record = $config_dir->read($name); // If the field config is not install, install it. if (!FieldConfig::loadByName( $config_record['entity_type'], $config_record['bundle'], $config_record['field_name']) ) { FieldConfig::create($config_record)->save(); } } // If there is no media yet on the content type, // then install the type of hero image field. if (!in_array($id, $cts_with_media)) { // Name of the hero image field. $name = 'field.field.node.' . $id . '.field_uw_hero_image'; // Get the config from the yml into an array. $config_record = $config_dir->read($name); // If the field config is not install, install it. if (!FieldConfig::loadByName($config_record['entity_type'], $config_record['bundle'], $config_record['field_name'])) { FieldConfig::create($config_record)->save(); } } // Get all the nodes of the content type. $nodes = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['type' => $id]); // Step through each of the nodes and set the default // values of the fields. foreach ($nodes as $node) { // Set default values for banners. $node->field_uw_banner = NULL; $node->field_uw_media_width = 'uw_lbs_full_width'; $node->field_uw_slide_speed = 7000; $node->field_uw_transition_speed = 400; $node->field_uw_autoplay = TRUE; $node->field_uw_text_overlay_style = 'full-width'; // If the content type does not have media yet, // set the default value for type of media. if (!in_array($id, $cts_with_media)) { $node->field_uw_type_of_media = NULL; } // Save the node. $node->save(); } } // Ensure that we have some data to put back in the DB. if (!empty($node_data)) { // Step through all the tables and insert back into // the database. foreach ($node_data as $table => $data) { // Get all the rows from the table. foreach ($data as $field_data) { // Reset the fields array, so we are working with // a blank array to insert. $fields = []; // Step through all the entries in the row and add // to the fields array, this makes it much easier to // do one insert command. foreach ($field_data as $key => $value) { $fields[$key] = $value; } // Insert the row into the database. $database->insert($table) ->fields($fields) ->execute(); } } } } /** * Swap the order of content author and editor roles. */ function uw_cfg_common_update_9107(&$sandbox) { // The original weight of content editor role is 5. // The original weight of content author role is 4. $role_ids = [ 'uw_role_content_editor' => 4, 'uw_role_content_author' => 5, ]; // Set new weight of content editor role as 4. // Set new weight of content author role as 5. foreach ($role_ids as $role_id => $weight) { $role = Role::load($role_id); $role->setWeight($weight); $role->save(); } } /** * Add new path field for most nodes. */ function uw_cfg_common_update_9108(&$sandbox) { // The query. $query = \Drupal::entityQuery('node'); // The or condition for the query. $group = $query->orConditionGroup(); // The number of nodes per batch. $nodes_per_batch = 50; // Get the content types to batch. $content_types = _uw_get_node_types(); // If there is no batching, set it up. if (!isset($sandbox['total'])) { \Drupal::logger('uw_cfg_common')->info('9108 - Setting counters'); $sandbox['total'] = 0; $sandbox['processed'] = 0; $sandbox['#finished'] = 0; $sandbox['pre_batch'] = FALSE; } // If we have not run the batch, run the stuff requried before // we actually run the batch. if (!$sandbox['pre_batch']) { \Drupal::logger('uw_cfg_common')->info('9108 - running pre_batch'); // Set the field storage config. _uw_set_fieldable_path_storage_config(); // Step through each of conent types and add the group or. foreach ($content_types as $content_type) { // Add the content type to the or condition. $group->condition('type', $content_type, '='); } // Get all the nids. $nids = $query->condition($group) ->accessCheck(FALSE) ->execute(); // Set the or condition into the sandbox. $sandbox['group'] = $group; // Set the total number of nids into the sandbox. $sandbox['total'] = count($nids); // To prevent repeating the process on next batch. $sandbox['pre_batch'] = TRUE; } \Drupal::logger('uw_cfg_common')->info('9108 - starting fieldable path node'); // Set the field path in the node for each content type. _uw_set_feildable_path_node($content_types); \Drupal::logger('uw_cfg_common')->info('9108 - ending fieldable path node'); // Get the nids for the content type. We do it this // way so that we do not load all the node objects // at once, which was causing memory errors on // Pantheon. Bypassing access check. Work in batches of 50. $nids = \Drupal::entityQuery('node') ->condition($sandbox['group']) ->accessCheck(FALSE) ->range($sandbox['processed'], $nodes_per_batch) ->execute(); \Drupal::logger('uw_cfg_common')->info('9108 - starting node loop - ' . count($nids) . ' - ' . $sandbox['processed'] . ' - ' . $nodes_per_batch); // Step through each of the nids and perform the // update tasks for fieldable path. foreach ($nids as $nid) { // Load the actual node, this way we are only // loading one full node object at a time. $entity = \Drupal::entityTypeManager() ->getStorage('node') ->load($nid); // If there is no path, skip this node. if (!$entity->hasField('path')) { return; } // Load entity's internal path (i.e. /node/2). $internal_path = $entity->toUrl()->getInternalPath(); $alias = \Drupal::service('path_alias.manager') ->getAliasByPath('/' . $internal_path); // Update the fieldable path field. \Drupal::service('fieldable_path.controller') ->updateFieldablePath($entity, ['alias' => $alias]); } \Drupal::logger('uw_cfg_common')->info('9108 - ending node loop'); // Update the number of nids processed. $sandbox['processed'] += count($nids); // Set the message to display. $message = t( 'Processing nodes of - @p/@t.', [ '@p' => $sandbox['processed'], '@t' => $sandbox['total'] ] ); // If we are done, then complete the batching. if ($sandbox['processed'] >= $sandbox['total']) { \Drupal::logger('uw_cfg_common')->info('9108 - all nodes proccessed'); $sandbox['#finished'] = 1; return $message; } // Update the finished, when done processed / total will be 1. $sandbox['#finished'] = ($sandbox['processed'] / $sandbox['total']); return $message; } /** * Function to set the fieldable path storage config. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ function _uw_set_fieldable_path_storage_config() { // The modules to install. $modules = [ 'fieldable_path', 'jsonapi', 'jsonapi_extras', ]; // Install the modules. \Drupal::service('module_installer')->install($modules); // Get the path to uw_cfg_common. $module_path = Drupal::service('extension.list.module') ->getPath('uw_cfg_common'); // Get the config path to uw_cfg_common. $config_path = $module_path . '/config/install'; // Get a new file source object to uw_cfg_common config path. $source = new FileStorage($config_path); // The config storage service. $config_storage = \Drupal::service('config.storage'); // Write the new storage of jsonapi_extras settings. We need this // since when we do a feature revert, the database is not setup // correctly causing a serialization error. This will alleviate // that error. $config_storage->write( 'jsonapi_extras.settings', $source->read('jsonapi_extras.settings') ); // The field storage name. $name = 'field.storage.node.field_path'; // Get the path to cfg common config install directory. $path = \Drupal::service('extension.list.module') ->getPath('uw_cfg_common') . '/config/install/'; $config_dir = new FileStorage($path); // Get the config from the yml file into an array. $config_record = $config_dir->read($name); // Get the entity type. $entity_type = \Drupal::service('config.manager') ->getEntityTypeIdByName($name); // Get the storage. $storage = \Drupal::entityTypeManager()->getStorage($entity_type); // Create the new field from the converted yml. $field = $storage->createFromStorageRecord($config_record); // Save the new field. $field->save(); } /** * Function to get the uw content types. * * @return array * The array of content types. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ function _uw_get_node_types() { // The content types that are not getting any changes. $cts_not_to_install = [ 'uw_ct_sidebar', 'uw_ct_site_footer', 'uw_ct_expand_collapse_group', ]; // Get all the node types. $node_types = \Drupal::entityTypeManager() ->getStorage('node_type') ->loadMultiple(); // Step through each node type and get the path to // the module and the machine name. foreach ($node_types as $node_type) { // Get the id from the node type. $id = $node_type->id(); // Ensure we are only getting the node type // that need updating. if (!in_array($id, $cts_not_to_install)) { // Catalogs and opportunities have different paths // and ids, so setup the content types array with // the correct info. if ($id === 'uw_ct_catalog_item') { $content_types['uw_ct_catalog'] = $id; } elseif ($id === 'uw_ct_opportunity') { $content_types['uw_ct_opportunities'] = $id; } else { $content_types[$id] = $id; } } } return $content_types; } /** * Function to set the fieldable on a node. * * @param array $content_types * The array of content types. * * @throws \Drupal\Core\Entity\EntityStorageException */ function _uw_set_feildable_path_node(array $content_types) { // Step through each of the content types and install the fields, // and also setup default values for the fields. foreach ($content_types as $path => $content_type) { // Get the path to the content type. $path = \Drupal::service('extension.list.module')->getPath($path) . '/config/install/'; $config_dir = new FileStorage($path); // Get the name of the field. $name = 'field.field.node.' . $content_type . '.field_path'; // Get the config from the yml into an array. $config_record = $config_dir->read($name); if ($config_record) { // If the field config is not install, install it. if (!FieldConfig::loadByName( $config_record['entity_type'], $config_record['bundle'], $config_record['field_name']) ) { FieldConfig::create($config_record)->save(); } } } }