diff --git a/config/prod/services.yml b/config/prod/services.yml index 5e5c41921..719df8a81 100644 --- a/config/prod/services.yml +++ b/config/prod/services.yml @@ -121,6 +121,16 @@ services: $connectorFactory: '@cloud.v3.connector_factory' $application: '@Acquia\Cli\Application' $credentials: '@cloud.credentials' + # Source commands talk to Cloud API v3. + Acquia\Cli\Command\Source\LinkCommand: + arguments: + $cloudApiClientService: '@Acquia\Cli\CloudApi\V3ClientService' + Acquia\Cli\Command\Source\ConfigPullCommand: + arguments: + $cloudApiClientService: '@Acquia\Cli\CloudApi\V3ClientService' + Acquia\Cli\Command\Source\ConfigPushCommand: + arguments: + $cloudApiClientService: '@Acquia\Cli\CloudApi\V3ClientService' AcquiaCloudApi\Connector\ConnectorInterface: alias: Acquia\Cli\CloudApi\ConnectorFactory AcquiaCloudApi\Connector\Connector: diff --git a/src/Command/Source/ConfigCommandBase.php b/src/Command/Source/ConfigCommandBase.php new file mode 100644 index 000000000..dc67f77c6 --- /dev/null +++ b/src/Command/Source/ConfigCommandBase.php @@ -0,0 +1,48 @@ +addOption('site', null, InputOption::VALUE_REQUIRED, 'The Source site ID (defaults to the one recorded by acli source:link)') + ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'); + } + + /** + * Whether --format=json was passed: the outcome is then the only stdout. + * + * @throws \Acquia\Cli\Exception\AcquiaCliException + */ + protected function outputsJson(): bool + { + $format = $this->input->getOption('format'); + if (!in_array($format, ['txt', 'json'], true)) { + throw new AcquiaCliException('Unknown output format "{format}". Use txt or json.', ['format' => $format]); + } + return $format === 'json'; + } + + /** + * @throws \Acquia\Cli\Exception\AcquiaCliException + */ + protected function determineSourceSite(string $workingCopyDir): string + { + $siteId = $this->input->getOption('site') ?? $this->sourceDatastore($workingCopyDir)->get('source_site_id'); + if (!$siteId) { + throw new AcquiaCliException('Could not determine the Source site. Pass --site= or run acli source:link first.'); + } + return $siteId; + } +} diff --git a/src/Command/Source/ConfigPullCommand.php b/src/Command/Source/ConfigPullCommand.php new file mode 100644 index 000000000..0597b51fd --- /dev/null +++ b/src/Command/Source/ConfigPullCommand.php @@ -0,0 +1,49 @@ +outputsJson(); + $root = $this->workingCopyDir(); + $siteId = $this->determineSourceSite($root); + $response = $this->cloudApiClientService->getClient()->request('get', "/source-sites/$siteId/config"); + $files = SourceConfigDocument::toFiles($response->configuration); + + // Write everything into a sibling directory first, so that a failure + // halfway leaves the existing .acquia/config untouched. + $configDir = "$root/.acquia/config"; + $tmpDir = "$configDir.tmp"; + $filesystem = $this->localMachineHelper->getFilesystem(); + $filesystem->remove($tmpDir); + try { + foreach ($files as $path => $contents) { + $filesystem->dumpFile("$tmpDir/$path", $contents); + } + $filesystem->remove($configDir); + $filesystem->rename($tmpDir, $configDir); + } finally { + $filesystem->remove($tmpDir); + } + if ($json) { + $output->writeln(json_encode(['directory' => $configDir, 'files' => array_keys($files)], JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT)); + } else { + $this->io->success(sprintf('Exported %d configuration files from Source site %s to %s', count($files), $siteId, $configDir)); + } + + return Command::SUCCESS; + } +} diff --git a/src/Command/Source/ConfigPushCommand.php b/src/Command/Source/ConfigPushCommand.php new file mode 100644 index 000000000..95bbfeea8 --- /dev/null +++ b/src/Command/Source/ConfigPushCommand.php @@ -0,0 +1,132 @@ +addOption('force', 'f', InputOption::VALUE_NONE, 'Skip the confirmation prompt (required when non-interactive)'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $json = $this->outputsJson(); + $root = $this->workingCopyDir(); + $siteId = $this->determineSourceSite($root); + $configDir = "$root/.acquia/config"; + if (!is_dir($configDir)) { + throw new AcquiaCliException('{dir} does not exist. Run acli source:cms:config:pull first.', ['dir' => $configDir]); + } + $files = []; + foreach ($this->localMachineHelper->getFinder()->files()->in($configDir)->name('*.yml') as $file) { + $files[$file->getRelativePathname()] = $file->getContents(); + } + $document = SourceConfigDocument::fromFiles($files); + + if (!$input->getOption('force')) { + if (!$input->isInteractive()) { + throw new AcquiaCliException('Pass --force to push without confirmation when running non-interactively.'); + } + if (!$this->io->confirm("Replace the configuration of Source site $siteId with the contents of $configDir? The site is put in maintenance mode and its database is backed up first.")) { + return Command::SUCCESS; + } + } + + $client = $this->cloudApiClientService->getClient(); + try { + $client->request('put', "/source-sites/$siteId/config", ['json' => ['configuration' => $document]]); + } catch (ApiErrorException $e) { + // 409: the site is already importing (or exporting) configuration. + if ($e->getResponseBody()->error === 'conflict') { + throw new AcquiaCliException('A configuration sync is already running for Source site {site}. Wait for it to finish, then push again.', ['site' => $siteId]); + } + throw $e; + } + + if ($json) { + // The import resource is the only stdout: silence the spinner and the report. + $this->output = new NullOutput(); + $this->io = new SymfonyStyle($input, $this->output); + } + $import = $this->waitForImport($client, $siteId); + $exitCode = $this->reportImport($siteId, $import); + if ($json) { + $output->writeln(json_encode($import, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT)); + } + + return $exitCode; + } + + /** + * Polls the site's latest import until it is no longer running. + */ + private function waitForImport(Client $client, string $siteId): object + { + $import = null; + $error = null; + $poll = static function () use ($client, $siteId, &$import, &$error): bool { + try { + $import = $client->request('get', "/source-sites/$siteId/config/import"); + return $import->status !== 'running'; + } catch (Throwable $e) { + // An exception escaping the loop would leave its timers behind. + $error = $e; + return true; + } + }; + LoopHelper::getLoopy($this->output, $this->io, 'Importing configuration', $poll, static function (): void { + }); + if ($error !== null) { + throw new AcquiaCliException('The import was accepted but its outcome is unknown ({reason}). Check the site before pushing again. The import may still finish, and the status it reports may then be that of a later import.', ['reason' => $error->getMessage()]); + } + return $import; + } + + private function reportImport(string $siteId, object $import): int + { + switch ($import->status) { + case 'succeeded': + $this->io->success("Imported .acquia/config into Source site $siteId."); + return Command::SUCCESS; + + case 'refused': + $this->io->error("Source site $siteId refused the configuration; nothing was imported:"); + foreach ($import->violations ?? [] as $violation) { + $location = match (true) { + isset($violation->collection) => "$violation->collection: $violation->config", + isset($violation->config) => $violation->config, + default => 'document', + }; + $this->io->writeln(sprintf(' - %s [%s]: %s', $location, $violation->code, $violation->message)); + } + return Command::FAILURE; + + case 'failed': + $this->io->error("The import into Source site $siteId failed; the site was rolled back to its previous configuration."); + return Command::FAILURE; + } + // Only the 45-minute watchdog in LoopHelper can leave the status at "running". + throw new AcquiaCliException('The import was accepted but its outcome is unknown (status {status}). Check the site before pushing again. The import may still finish, and the status it reports may then be that of a later import.', ['status' => $import->status]); + } +} diff --git a/src/Command/Source/LinkCommand.php b/src/Command/Source/LinkCommand.php new file mode 100644 index 000000000..58f2c2b8e --- /dev/null +++ b/src/Command/Source/LinkCommand.php @@ -0,0 +1,54 @@ +addArgument('sourceSiteId', InputArgument::OPTIONAL, 'The Source site ID'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $datastore = $this->sourceDatastore($this->workingCopyDir()); + $client = $this->cloudApiClientService->getClient(); + if ($siteId = $input->getArgument('sourceSiteId')) { + // The ID becomes a URL path segment. + if (!preg_match('/^[a-zA-Z0-9-]+$/', $siteId)) { + throw new AcquiaCliException('"{id}" is not a valid Source site ID: only letters, digits and hyphens are allowed.', ['id' => $siteId]); + } + $site = $client->request('get', "/source-sites/$siteId"); + } else { + if ($linked = $datastore->get('source_site_id')) { + $output->writeln("This working copy is already linked to Source site $linked. Run acli source:link to link it to another site."); + return 1; + } + if (!$input->isInteractive()) { + throw new AcquiaCliException('Pass the Source site ID as the sourceSiteId argument when running non-interactively.'); + } + $sites = $client->request('get', '/source-sites'); + if (!$sites) { + throw new AcquiaCliException('There are no Source sites to link to.'); + } + // ponytail: first page of /source-sites only; add pagination when a subscription exceeds one page. + $site = $this->promptChooseFromObjectsOrArrays($sites, 'id', 'label', 'Select a Source site'); + } + $datastore->set('source_site_id', $site->id); + $this->io->success("Linked this working copy to Source site $site->label ($site->id) by writing to $datastore->filepath"); + + return Command::SUCCESS; + } +} diff --git a/src/Command/Source/SourceCommandBase.php b/src/Command/Source/SourceCommandBase.php new file mode 100644 index 000000000..9c77f92c6 --- /dev/null +++ b/src/Command/Source/SourceCommandBase.php @@ -0,0 +1,42 @@ +cwd ?? getcwd()); + } + + /** + * The .acquia-cli.yml at the working copy root, where the Source site is recorded. + */ + protected function sourceDatastore(string $workingCopyDir): AcquiaCliDatastore + { + return new AcquiaCliDatastore($this->localMachineHelper, new AcquiaCliConfig(), $workingCopyDir . '/.acquia-cli.yml'); + } +} diff --git a/src/Config/AcquiaCliConfig.php b/src/Config/AcquiaCliConfig.php index 8124fcb0e..64a32b9d4 100644 --- a/src/Config/AcquiaCliConfig.php +++ b/src/Config/AcquiaCliConfig.php @@ -21,6 +21,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->getRootNode() ->children() ->scalarNode('cloud_app_uuid')->end() + ->scalarNode('source_site_id')->end() ->arrayNode('push') ->children() ->arrayNode('artifact') diff --git a/src/Helpers/LocalMachineHelper.php b/src/Helpers/LocalMachineHelper.php index 44094146c..129c56d65 100644 --- a/src/Helpers/LocalMachineHelper.php +++ b/src/Helpers/LocalMachineHelper.php @@ -317,6 +317,23 @@ public static function getProjectDir(): ?string return null; } + /** + * Gets the root of the Source working copy that contains $cwd. + * + * That is the nearest directory at or above $cwd containing + * .acquia/config; when there is none (nothing pulled yet), $cwd itself. + * + * Neither of the two existing directory lookups fits: getProjectDir() + * finds a Drupal project by its docroot, which a Source working copy does + * not have, and getConfigDir() is the user's own acli configuration + * directory (~/.acquia), which holds cloud_api.conf and is never a working + * copy. + */ + public static function getSourceWorkingCopyDir(string $cwd): string + { + return self::findDirectoryContainingFiles($cwd, ['.acquia/config']) ?: $cwd; + } + /** * Traverses file system upwards in search of a given file. * diff --git a/src/Helpers/SourceConfigDocument.php b/src/Helpers/SourceConfigDocument.php new file mode 100644 index 000000000..0cb0134cd --- /dev/null +++ b/src/Helpers/SourceConfigDocument.php @@ -0,0 +1,101 @@ + config name => values. The + * default collection is keyed '' and maps to the directory root; any other + * collection maps to a subdirectory with its dots turned into slashes + * (language.nl => language/nl). Each config object is one .yml file. + * Files are encoded and decoded exactly like Drupal core does, so a pull + * followed by a push reproduces the document byte for byte. + */ +final class SourceConfigDocument +{ + /** + * @return array + * Relative file path => file contents. + */ + public static function toFiles(string $yaml): array + { + $document = self::decode($yaml); + if (!is_array($document) || $document === []) { + throw new AcquiaCliException('The configuration document is empty or not a map of collections.'); + } + $files = []; + foreach ($document as $collection => $objects) { + $collection = (string) $collection; + if (!is_array($objects)) { + throw new AcquiaCliException('Collection "{collection}" is not a map of configuration objects.', ['collection' => $collection]); + } + $dir = $collection === '' ? '' : str_replace('.', '/', self::assertSafe('collection', $collection, explode('.', $collection))) . '/'; + foreach ($objects as $name => $values) { + $name = (string) $name; + $files[$dir . self::assertSafe('configuration', $name, [$name]) . '.yml'] = self::encode($values); + } + } + // Every path was validated above, so a bad document yields no files at all. + return $files; + } + + /** + * @param array $files + * Relative file path => file contents. + */ + public static function fromFiles(array $files): string + { + $document = []; + foreach ($files as $path => $yaml) { + $path = str_replace('\\', '/', $path); + $dir = dirname($path); + $collection = $dir === '.' ? '' : str_replace('/', '.', $dir); + try { + $document[$collection][basename($path, '.yml')] = self::decode($yaml); + } catch (ParseException $e) { + throw new AcquiaCliException('{file} is not valid YAML: {error}', ['file' => $path, 'error' => $e->getMessage()]); + } + } + ksort($document); + foreach ($document as &$objects) { + ksort($objects); + } + return self::encode($document); + } + + /** + * Rejects a collection or config name that could escape .acquia/config. + * + * @param list $segments + * The path segments the name becomes; a segment must not be '', '.' or + * '..' nor contain a slash, backslash or NUL. "a..b" is a legal segment. + */ + private static function assertSafe(string $what, string $name, array $segments): string + { + foreach ($segments as $segment) { + if (in_array($segment, ['', '.', '..'], true) || preg_match('#[/\\\\\0]#', $segment)) { + throw new AcquiaCliException('"{name}" is not a valid {what} name.', ['name' => $name, 'what' => $what]); + } + } + return $name; + } + + private static function decode(string $yaml): mixed + { + return (new Parser())->parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE | Yaml::PARSE_CUSTOM_TAGS); + } + + private static function encode(mixed $data): string + { + return (new Dumper(2))->dump($data, PHP_INT_MAX, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE | Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); + } +} diff --git a/tests/fixtures/source-config/README.md b/tests/fixtures/source-config/README.md new file mode 100644 index 000000000..c2175640b --- /dev/null +++ b/tests/fixtures/source-config/README.md @@ -0,0 +1,36 @@ +# Source configuration fixture + +`document.yml` is the configuration document a Source site returns, and +`expected/` is that same document written out as `.acquia/config` files. +Both were produced by the site itself (Drupal core's YAML encoder and +`FileStorage`), not by Acquia CLI, so the tests prove byte-for-byte fidelity +in both directions. + +To regenerate from a haas-drupal DDEV checkout: a fresh `standard` install, +Dutch added, and two `language.nl` overrides so that `language/nl/` is +exercised. The expected tree is written by core's `FileStorage` so that the +layout is never reimplemented here. + +```shell +cd ~/Work/haas-drupal +ddev si # fresh install, standard recipe +ddev drush language:add nl -y +ddev drush php:eval '$o = \Drupal::service("language.config_factory_override"); $o->getOverride("nl", "system.site")->set("name", "Mijn site")->set("slogan", "Een slogan")->save(); $o->getOverride("nl", "node.type.article")->set("name", "Artikel")->set("description", "Een artikel")->save();' +ddev exec 'vendor/bin/dr source:config:dump --single-yaml' | tee ~/Work/cli/tests/fixtures/source-config/document.yml | ddev exec 'cat > /tmp/doc.yml' +ddev exec 'cat > /tmp/write-expected.php' <<'PHP' + $objects) { + $storage = $default->createCollection($collection); + foreach ($objects as $name => $data) { + $storage->write($name, $data); + } +} +PHP +ddev drush php:script /tmp/write-expected.php +cd ~/Work/cli/tests/fixtures/source-config && rm -rf expected && mkdir expected +(cd ~/Work/haas-drupal && ddev exec 'cd /tmp/expected && find . -name .htaccess -delete && tar -cf - .') | tar -xf - -C expected +``` diff --git a/tests/fixtures/source-config/document.yml b/tests/fixtures/source-config/document.yml new file mode 100644 index 000000000..649c418be --- /dev/null +++ b/tests/fixtures/source-config/document.yml @@ -0,0 +1,5916 @@ +'': + core.base_field_override.node.article.promote: + uuid: cf936d55-e374-43fb-a904-dada6a58afd2 + langcode: en + status: true + dependencies: + config: + - node.type.article + _core: + default_config_hash: GrzL4TIZFEHW2o6Qr_sTIT2DWt88DwkgC2NWj3xE46I + id: node.article.promote + field_name: promote + entity_type: node + bundle: article + label: 'Promoted to front page' + description: '' + required: false + translatable: true + default_value: + - + value: false + default_value_callback: '' + settings: + on_label: 'On' + off_label: 'Off' + field_type: boolean + core.base_field_override.node.person.status: + uuid: 9cfb97b6-b6f5-40dc-bd3b-546cba522619 + langcode: en + status: true + dependencies: + config: + - node.type.person + _core: + default_config_hash: y-kCVhlvg7OvtzBrI0hCYIcduf55A5oRXl9bDGjHSLc + id: node.person.status + field_name: status + entity_type: node + bundle: person + label: Published + description: '' + required: false + translatable: true + default_value: + - + value: false + default_value_callback: '' + settings: + on_label: 'On' + off_label: 'Off' + field_type: boolean + core.base_field_override.node.person.title: + uuid: 37ce7281-601d-4fc1-aa6b-d9a0a9bd97d8 + langcode: en + status: true + dependencies: + config: + - node.type.person + _core: + default_config_hash: ppJksNIlmg7WiVfHydPDROhK9ceGLvo7Lm1ejQfbmQE + id: node.person.title + field_name: title + entity_type: node + bundle: person + label: 'Display name' + description: '' + required: true + translatable: true + default_value: { } + default_value_callback: '' + settings: { } + field_type: string + core.entity_form_display.media.document.default: + uuid: a28bd6b1-bc3d-4b6f-82a1-56b99fdfdada + langcode: en + status: true + dependencies: + config: + - field.field.media.document.categories + - field.field.media.document.media_file + - field.field.media.document.tags + - media.type.document + module: + - field_group + - file + - haas_content + - metatag + - path + third_party_settings: + field_group: + group_taxonomy: + children: + - categories + - tags + label: Taxonomy + region: content + parent_name: '' + weight: 9 + format_type: fieldset + format_settings: + classes: '' + show_empty_fields: false + id: '' + description: '' + required_fields: false + id: media.document.default + targetEntityType: media + bundle: document + mode: default + content: + categories: + type: entity_reference_tagify_hierarchical + weight: 27 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Choose categories' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + created: + type: datetime_timestamp + weight: 4 + region: content + settings: { } + third_party_settings: { } + media_file: + type: file_generic + weight: 1 + region: content + settings: + progress_indicator: throbber + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 6 + region: content + settings: { } + third_party_settings: { } + replace_file: + weight: 2 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 7 + region: content + settings: + display_label: true + third_party_settings: { } + tags: + type: entity_reference_tagify + weight: 28 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Add tags' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + translation: + weight: 5 + region: content + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 3 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + langcode: true + tags: true + core.entity_form_display.media.document.media_library: + uuid: 2e9313c0-f149-45a0-99ea-02a7f9370491 + langcode: en + status: true + dependencies: + config: + - core.entity_form_mode.media.media_library + - field.field.media.document.categories + - field.field.media.document.media_file + - field.field.media.document.tags + - media.type.document + module: + - metatag + id: media.document.media_library + targetEntityType: media + bundle: document + mode: media_library + content: + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + created: true + langcode: true + media_file: true + path: true + replace_file: true + status: true + tags: true + translation: true + uid: true + core.entity_form_display.media.image.default: + uuid: 834789b9-8f75-415c-8d3d-83f5848a2418 + langcode: en + status: true + dependencies: + config: + - field.field.media.image.categories + - field.field.media.image.media_image + - field.field.media.image.tags + - image.style.media_library + - media.type.image + module: + - field_group + - focal_point + - haas_content + - metatag + - path + third_party_settings: + field_group: + group_taxonomy: + children: + - categories + - tags + label: Taxonomy + region: content + parent_name: '' + weight: 10 + format_type: fieldset + format_settings: + classes: '' + show_empty_fields: false + id: '' + description: '' + required_fields: false + id: media.image.default + targetEntityType: media + bundle: image + mode: default + content: + categories: + type: entity_reference_tagify_hierarchical + weight: 27 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Choose categories' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + created: + type: datetime_timestamp + weight: 6 + region: content + settings: { } + third_party_settings: { } + media_image: + type: image_focal_point + weight: 1 + region: content + settings: + progress_indicator: throbber + preview_image_style: media_library + preview_link: true + offsets: '50,50' + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 8 + region: content + settings: { } + third_party_settings: { } + replace_file: + weight: 2 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 9 + region: content + settings: + display_label: true + third_party_settings: { } + tags: + type: entity_reference_tagify + weight: 28 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Add tags' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + translation: + weight: 7 + region: content + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 3 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + langcode: true + tags: true + core.entity_form_display.media.image.media_library: + uuid: 964d313a-3fe4-4398-8959-73258556ef11 + langcode: en + status: true + dependencies: + config: + - core.entity_form_mode.media.media_library + - field.field.media.image.categories + - field.field.media.image.media_image + - field.field.media.image.tags + - image.style.media_library + - media.type.image + module: + - image + - metatag + id: media.image.media_library + targetEntityType: media + bundle: image + mode: media_library + content: + media_image: + type: image_image + weight: 5 + region: content + settings: + progress_indicator: throbber + preview_image_style: media_library + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + created: true + langcode: true + path: true + replace_file: true + status: true + tags: true + translation: true + uid: true + core.entity_form_display.media.remote_video.default: + uuid: e785e143-ba3c-4c6f-baa8-4756b8f507b2 + langcode: en + status: true + dependencies: + config: + - field.field.media.remote_video.categories + - field.field.media.remote_video.media_oembed_video + - field.field.media.remote_video.tags + - media.type.remote_video + module: + - field_group + - haas_content + - media + - metatag + - path + third_party_settings: + field_group: + group_taxonomy: + children: + - categories + - tags + label: Taxonomy + region: content + parent_name: '' + weight: 9 + format_type: fieldset + format_settings: + classes: '' + show_empty_fields: false + id: '' + description: '' + required_fields: false + id: media.remote_video.default + targetEntityType: media + bundle: remote_video + mode: default + content: + categories: + type: entity_reference_tagify_hierarchical + weight: 27 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Choose categories' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + created: + type: datetime_timestamp + weight: 5 + region: content + settings: { } + third_party_settings: { } + media_oembed_video: + type: oembed_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + path: + type: path + weight: 7 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 8 + region: content + settings: + display_label: true + third_party_settings: { } + tags: + type: entity_reference_tagify + weight: 28 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Add tags' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + translation: + weight: 6 + region: content + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 2 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + langcode: true + name: true + tags: true + core.entity_form_display.media.remote_video.media_library: + uuid: 44a32894-5844-4d96-8667-ccd987cf8fbf + langcode: en + status: true + dependencies: + config: + - core.entity_form_mode.media.media_library + - field.field.media.remote_video.categories + - field.field.media.remote_video.media_oembed_video + - field.field.media.remote_video.tags + - media.type.remote_video + module: + - metatag + id: media.remote_video.media_library + targetEntityType: media + bundle: remote_video + mode: media_library + content: + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + created: true + langcode: true + media_oembed_video: true + path: true + scheduler_settings: true + status: true + tags: true + translation: true + uid: true + core.entity_form_display.media.video.default: + uuid: 5264cca0-f083-456b-8107-a31532ebd404 + langcode: en + status: true + dependencies: + config: + - field.field.media.video.categories + - field.field.media.video.media_video_file + - field.field.media.video.tags + - media.type.video + module: + - field_group + - file + - haas_content + - metatag + - path + third_party_settings: + field_group: + group_taxonomy: + children: + - categories + - tags + label: Taxonomy + region: content + parent_name: '' + weight: 10 + format_type: fieldset + format_settings: + classes: '' + show_empty_fields: false + id: '' + description: '' + required_fields: false + id: media.video.default + targetEntityType: media + bundle: video + mode: default + content: + categories: + type: entity_reference_tagify_hierarchical + weight: 27 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Choose categories' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + created: + type: datetime_timestamp + weight: 10 + region: content + settings: { } + third_party_settings: { } + media_video_file: + type: file_generic + weight: 0 + region: content + settings: + progress_indicator: throbber + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: -5 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 30 + region: content + settings: { } + third_party_settings: { } + replace_file: + weight: 1 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 100 + region: content + settings: + display_label: true + third_party_settings: { } + tags: + type: entity_reference_tagify + weight: 28 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Add tags' + suggestions_dropdown: 0 + show_entity_id: 0 + third_party_settings: { } + translation: + weight: 5 + region: content + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 5 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + langcode: true + tags: true + core.entity_form_display.media.video.media_library: + uuid: c226360d-9d96-4673-965b-ecef5954f9e3 + langcode: en + status: true + dependencies: + config: + - core.entity_form_mode.media.media_library + - field.field.media.video.categories + - field.field.media.video.media_video_file + - field.field.media.video.tags + - media.type.video + module: + - file + - metatag + id: media.video.media_library + targetEntityType: media + bundle: video + mode: media_library + content: + media_video_file: + type: file_generic + weight: 0 + region: content + settings: + progress_indicator: throbber + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 26 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: -5 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + hidden: + categories: true + created: true + langcode: true + metatag: true + path: true + replace_file: true + status: true + tags: true + uid: true + core.entity_form_display.node.article.default: + uuid: ae410a68-db84-4959-94d5-28881553eee5 + langcode: en + status: true + dependencies: + config: + - field.field.node.article.author_profile + - field.field.node.article.body + - field.field.node.article.categories + - field.field.node.article.cover_image + - field.field.node.article.media + - field.field.node.article.related_articles + - field.field.node.article.tags + - node.type.article + - workflows.workflow.editorial + module: + - content_moderation + - field_group + - haas_content + - media_library + - metatag + - path + - scheduler + - scheduler_content_moderation_integration + - text + third_party_settings: + field_group: + group_taxonomy: + children: + - categories + - tags + label: Taxonomy + region: content + parent_name: '' + weight: 8 + format_type: fieldset + format_settings: + classes: '' + show_empty_fields: false + id: '' + description: '' + required_fields: false + group_media: + children: + - cover_image + - media + label: Media + region: content + parent_name: '' + weight: 10 + format_type: fieldset + format_settings: + classes: '' + show_empty_fields: false + id: '' + description: '' + required_fields: false + _core: + default_config_hash: cOT_33fZCrMJzsUb_qmwzIS0bhCLp-VAGFdGOsoC65c + id: node.article.default + targetEntityType: node + bundle: article + mode: default + content: + author_profile: + type: entity_reference_tagify + weight: 101 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Choose author profile' + suggestions_dropdown: 0 + show_entity_id: 0 + show_stacked: false + third_party_settings: { } + body: + type: text_textarea_with_summary + weight: 7 + region: content + settings: + rows: 9 + summary_rows: 3 + placeholder: '' + show_summary: false + third_party_settings: { } + categories: + type: entity_reference_tagify_hierarchical + weight: 13 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Choose categories' + suggestions_dropdown: 0 + show_entity_id: 0 + show_stacked: false + third_party_settings: { } + cover_image: + type: media_library_widget + weight: 14 + region: content + settings: + media_types: { } + third_party_settings: { } + created: + type: datetime_timestamp + weight: 2 + region: content + settings: { } + third_party_settings: { } + media: + type: media_library_widget + weight: 15 + region: content + settings: + media_types: { } + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 11 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + path: + type: path + weight: 3 + region: content + settings: { } + third_party_settings: { } + related_articles: + type: entity_reference_tagify + weight: 12 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Choose related articles' + suggestions_dropdown: 0 + show_entity_id: 0 + show_stacked: false + third_party_settings: { } + scheduler_settings: + weight: 5 + region: content + settings: { } + third_party_settings: { } + simple_sitemap: + weight: 10 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 6 + region: content + settings: + display_label: true + third_party_settings: { } + tags: + type: entity_reference_tagify + weight: 15 + region: content + settings: + match_operator: CONTAINS + match_limit: 20 + placeholder: 'Add tags' + suggestions_dropdown: 0 + show_entity_id: 0 + show_stacked: false + third_party_settings: { } + title: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + translation: + weight: 4 + region: content + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 1 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + url_redirects: + weight: 4 + region: content + settings: { } + third_party_settings: { } + hidden: { } + core.entity_form_display.node.person.default: + uuid: 3b1e48e8-d086-4ce1-ae8d-bbb2324f9fd9 + langcode: en + status: true + dependencies: + config: + - field.field.node.person.bio + - field.field.node.person.first_name + - field.field.node.person.job_title + - field.field.node.person.last_name + - field.field.node.person.profile_image + - node.type.person + - workflows.workflow.editorial + module: + - content_moderation + - media_library + - metatag + - path + - scheduler + - scheduler_content_moderation_integration + - text + _core: + default_config_hash: zHl0kW2YFAD4ks6O9qVmSfYQ8uMGh6H4ORrzGrUtMDc + id: node.person.default + targetEntityType: node + bundle: person + mode: default + content: + bio: + type: text_textarea + weight: 125 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + created: + type: datetime_timestamp + weight: 10 + region: content + settings: { } + third_party_settings: { } + first_name: + type: string_textfield + weight: 122 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + job_title: + type: string_textfield + weight: 124 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + last_name: + type: string_textfield + weight: 123 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 121 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + path: + type: path + weight: 30 + region: content + settings: { } + third_party_settings: { } + profile_image: + type: media_library_widget + weight: 126 + region: content + settings: + media_types: { } + third_party_settings: { } + simple_sitemap: + weight: 10 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 120 + region: content + settings: + display_label: true + third_party_settings: { } + title: + type: string_textfield + weight: -5 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 5 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + url_redirects: + weight: 50 + region: content + settings: { } + third_party_settings: { } + hidden: { } + core.entity_form_display.taxonomy_term.categories.default: + uuid: c0dd9b7b-2ce7-4987-af08-b3b749739676 + langcode: en + status: true + dependencies: + config: + - taxonomy.vocabulary.categories + module: + - metatag + - path + - text + id: taxonomy_term.categories.default + targetEntityType: taxonomy_term + bundle: categories + mode: default + content: + description: + type: text_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 101 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: -5 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 30 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 100 + region: content + settings: + display_label: true + third_party_settings: { } + translation: + weight: 10 + region: content + settings: { } + third_party_settings: { } + hidden: + langcode: true + core.entity_form_display.taxonomy_term.tags.default: + uuid: 7331f039-8381-412e-be3c-b616ddfc4e8f + langcode: en + status: true + dependencies: + config: + - taxonomy.vocabulary.tags + module: + - metatag + - path + - text + id: taxonomy_term.tags.default + targetEntityType: taxonomy_term + bundle: tags + mode: default + content: + description: + type: text_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + metatags: + type: metatag_firehose + weight: 101 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + name: + type: string_textfield + weight: -5 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 30 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 100 + region: content + settings: + display_label: true + third_party_settings: { } + translation: + weight: 10 + region: content + settings: { } + third_party_settings: { } + hidden: + langcode: true + cors_ui.configuration: + enabled: true + allowedHeaders: + - Authorization + - X-Consumer-ID + allowedMethods: + - OPTIONS + - GET + allowedOrigins: + - '*' + exposedHeaders: { } + maxAge: 5 + supportsCredentials: false + field.field.media.document.categories: + uuid: 4b35b9eb-3991-4686-b717-814599528fc6 + langcode: en + status: true + dependencies: + config: + - field.storage.media.categories + - media.type.document + - taxonomy.vocabulary.categories + id: media.document.categories + field_name: categories + entity_type: media + bundle: document + label: Categories + description: 'Categorize this media item.' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + categories: categories + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: categories + field_type: entity_reference + field.field.media.document.media_file: + uuid: 5d71e168-7bbc-4317-a5f0-63af2daf3818 + langcode: en + status: true + dependencies: + config: + - field.storage.media.media_file + - media.type.document + module: + - file + id: media.document.media_file + field_name: media_file + entity_type: media + bundle: document + label: File + description: '' + required: true + translatable: true + default_value: { } + default_value_callback: '' + settings: + handler: 'default:file' + handler_settings: { } + file_directory: '[date:custom:Y]-[date:custom:m]' + file_extensions: 'txt doc docx pdf' + max_filesize: '' + description_field: false + field_type: file + field.field.media.document.tags: + uuid: 10716007-318f-42e5-898e-2e7e31aedaa9 + langcode: en + status: true + dependencies: + config: + - field.storage.media.tags + - media.type.document + - taxonomy.vocabulary.tags + id: media.document.tags + field_name: tags + entity_type: media + bundle: document + label: Tags + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + tags: tags + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: '' + field_type: entity_reference + field.field.media.image.categories: + uuid: 3b25b8ea-2890-4585-a606-703499427fb5 + langcode: en + status: true + dependencies: + config: + - field.storage.media.categories + - media.type.image + - taxonomy.vocabulary.categories + id: media.image.categories + field_name: categories + entity_type: media + bundle: image + label: Categories + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + categories: categories + sort: + field: name + direction: asc + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.field.media.image.media_image: + uuid: c6acba7d-93e7-4eaf-9a57-3f4066cbf2be + langcode: en + status: true + dependencies: + config: + - field.storage.media.media_image + - media.type.image + module: + - image + id: media.image.media_image + field_name: media_image + entity_type: media + bundle: image + label: Image + description: '' + required: true + translatable: true + default_value: { } + default_value_callback: '' + settings: + handler: 'default:file' + handler_settings: { } + file_directory: '[date:custom:Y]-[date:custom:m]' + file_extensions: 'png gif jpg jpeg' + max_filesize: '5 MB' + max_resolution: '' + min_resolution: '' + alt_field: true + alt_field_required: true + title_field: false + title_field_required: false + default_image: + uuid: null + alt: '' + title: '' + width: null + height: null + field_type: image + field.field.media.image.tags: + uuid: 18850dbd-8d73-4316-a59e-74ad80b5cded + langcode: en + status: true + dependencies: + config: + - field.storage.media.tags + - media.type.image + - taxonomy.vocabulary.tags + id: media.image.tags + field_name: tags + entity_type: media + bundle: image + label: Tags + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + tags: tags + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: '' + field_type: entity_reference + field.field.media.remote_video.categories: + uuid: 0a76c8ff-04aa-4b44-995f-44317c17a749 + langcode: en + status: true + dependencies: + config: + - field.storage.media.categories + - media.type.remote_video + - taxonomy.vocabulary.categories + id: media.remote_video.categories + field_name: categories + entity_type: media + bundle: remote_video + label: Categories + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + categories: categories + sort: + field: name + direction: asc + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.field.media.remote_video.media_oembed_video: + uuid: 4fbb19e5-e680-4f44-9ebe-16d5dc0d8b3b + langcode: en + status: true + dependencies: + config: + - field.storage.media.media_oembed_video + - media.type.remote_video + id: media.remote_video.media_oembed_video + field_name: media_oembed_video + entity_type: media + bundle: remote_video + label: 'Remote video URL' + description: '' + required: true + translatable: true + default_value: { } + default_value_callback: '' + settings: { } + field_type: string + field.field.media.remote_video.tags: + uuid: 56fe693a-f53e-4115-afda-76e3c9582f4c + langcode: en + status: true + dependencies: + config: + - field.storage.media.tags + - media.type.remote_video + - taxonomy.vocabulary.tags + id: media.remote_video.tags + field_name: tags + entity_type: media + bundle: remote_video + label: Tags + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + tags: tags + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: '' + field_type: entity_reference + field.field.media.video.categories: + uuid: 16d504e1-c6c6-4708-8aa5-5cd43f5ca5f5 + langcode: en + status: true + dependencies: + config: + - field.storage.media.categories + - media.type.video + - taxonomy.vocabulary.categories + id: media.video.categories + field_name: categories + entity_type: media + bundle: video + label: Categories + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + categories: categories + sort: + field: name + direction: asc + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.field.media.video.media_video_file: + uuid: 0349bb02-418c-4e89-8071-dbca654ab025 + langcode: en + status: true + dependencies: + config: + - field.storage.media.media_video_file + - media.type.video + module: + - file + id: media.video.media_video_file + field_name: media_video_file + entity_type: media + bundle: video + label: 'Video file' + description: '' + required: true + translatable: true + default_value: { } + default_value_callback: '' + settings: + handler: 'default:file' + handler_settings: { } + file_directory: '[date:custom:Y]-[date:custom:m]' + file_extensions: 'mp4 webm' + max_filesize: '' + description_field: false + field_type: file + field.field.media.video.tags: + uuid: 626f4fbf-0f3d-4ea9-bccc-7bb31d7fc5c3 + langcode: en + status: true + dependencies: + config: + - field.storage.media.tags + - media.type.video + - taxonomy.vocabulary.tags + id: media.video.tags + field_name: tags + entity_type: media + bundle: video + label: Tags + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + tags: tags + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: '' + field_type: entity_reference + field.field.node.article.author_profile: + uuid: fc92655c-12ab-4ff9-89a3-249f3a301ca5 + langcode: en + status: true + dependencies: + config: + - field.storage.node.author_profile + - node.type.article + - node.type.person + _core: + default_config_hash: Ty2qU2W4G9orxERW-YGWOFpG99QRetfhcW0Nz_zyA6g + id: node.article.author_profile + field_name: author_profile + entity_type: node + bundle: article + label: 'Author profile' + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:node' + handler_settings: + target_bundles: + person: person + sort: + field: _none + direction: ASC + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.field.node.article.body: + uuid: 66b76963-a33f-4b51-83b1-bf1626b0e270 + langcode: en + status: true + dependencies: + config: + - field.storage.node.body + - node.type.article + module: + - text + _core: + default_config_hash: fEIT1MRCWfrspUK3KUN7kZgMo5HCXRGz1l1xcEPueoI + id: node.article.body + field_name: body + entity_type: node + bundle: article + label: Body + description: '' + required: false + translatable: true + default_value: { } + default_value_callback: '' + settings: + display_summary: true + required_summary: false + allowed_formats: { } + field_type: text_with_summary + field.field.node.article.categories: + uuid: c4587ecd-f4c2-4284-a6fe-f91e75ab3324 + langcode: en + status: true + dependencies: + config: + - field.storage.node.categories + - node.type.article + - taxonomy.vocabulary.categories + _core: + default_config_hash: Kez1LIlwG0qMCz8l7_1PCPiqwdLA3UTXdvY7kIuCDYQ + id: node.article.categories + field_name: categories + entity_type: node + bundle: article + label: Categories + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + categories: categories + sort: + field: name + direction: asc + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.field.node.article.cover_image: + uuid: a80e408f-75d9-4237-93ef-2d8033fb7eba + langcode: en + status: true + dependencies: + config: + - field.storage.node.cover_image + - media.type.image + - node.type.article + _core: + default_config_hash: XGSMo9v2c3WJIdt8MUxqH_y2Ea5WlgExYE07q2D6NTE + id: node.article.cover_image + field_name: cover_image + entity_type: node + bundle: article + label: 'Cover Image' + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:media' + handler_settings: + target_bundles: + image: image + sort: + field: _none + direction: ASC + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.field.node.article.media: + uuid: fffffa10-b9c7-490e-bcc1-e7c951d0b6f3 + langcode: en + status: true + dependencies: + config: + - field.storage.node.media + - media.type.document + - media.type.image + - media.type.remote_video + - media.type.video + - node.type.article + _core: + default_config_hash: drZbG6MSHksx6F7mhTYkCYn_Qr8Mmfg4Odu7lC2XDQ0 + id: node.article.media + field_name: media + entity_type: node + bundle: article + label: Media + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:media' + handler_settings: + target_bundles: + document: document + image: image + remote_video: remote_video + video: video + sort: + field: _none + direction: ASC + auto_create: false + auto_create_bundle: document + field_type: entity_reference + field.field.node.article.related_articles: + uuid: 22043365-10fa-491b-82ac-ae598f255055 + langcode: en + status: true + dependencies: + config: + - field.storage.node.related_articles + - node.type.article + _core: + default_config_hash: CfDI8wI2SVzG-SaJSGPrk2xofxa7CNZqvUUlpfy7_0s + id: node.article.related_articles + field_name: related_articles + entity_type: node + bundle: article + label: 'Related articles' + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:node' + handler_settings: + target_bundles: + article: article + sort: + field: _none + direction: ASC + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.field.node.article.tags: + uuid: ea9b5a2c-9373-431f-a705-54063c206984 + langcode: en + status: true + dependencies: + config: + - field.storage.node.tags + - node.type.article + - taxonomy.vocabulary.tags + _core: + default_config_hash: JQMY1oW3WFdyPXlo94jyczyGwYJqvkKhKmprchmnM5w + id: node.article.tags + field_name: tags + entity_type: node + bundle: article + label: Tags + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + tags: tags + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: '' + field_type: entity_reference + field.field.node.person.bio: + uuid: 05d4ad42-d287-47a9-b5a1-bbbd8e06ae5d + langcode: en + status: true + dependencies: + config: + - field.storage.node.bio + - node.type.person + module: + - text + _core: + default_config_hash: 7l84MnU9HwIC5EsqNNiorKGAnoeIYpfZmu8NRuPu9bc + id: node.person.bio + field_name: bio + entity_type: node + bundle: person + label: Bio + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + allowed_formats: { } + field_type: text_long + field.field.node.person.first_name: + uuid: e4c205e0-6c5f-445d-8f3f-753600f0632c + langcode: en + status: true + dependencies: + config: + - field.storage.node.first_name + - node.type.person + _core: + default_config_hash: TxsRv0JCOkhhHlfNBBAQdLD2Cz13Q6n5gb5Jtb3fQbA + id: node.person.first_name + field_name: first_name + entity_type: node + bundle: person + label: 'First name' + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: { } + field_type: string + field.field.node.person.job_title: + uuid: b5302b8e-e4bc-41fb-9da5-4e6c5392fb38 + langcode: en + status: true + dependencies: + config: + - field.storage.node.job_title + - node.type.person + _core: + default_config_hash: 6E9egi3l_sG2vypsaF3wsNizzes8Tniv7O9YiP_50mM + id: node.person.job_title + field_name: job_title + entity_type: node + bundle: person + label: 'Job title' + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: { } + field_type: string + field.field.node.person.last_name: + uuid: eefce936-4e7a-4d99-bbe4-830b56da5853 + langcode: en + status: true + dependencies: + config: + - field.storage.node.last_name + - node.type.person + _core: + default_config_hash: J_Dxi1m4ypCIQDm7rGRyGHMZEKlpH71lMBwQujdsbUI + id: node.person.last_name + field_name: last_name + entity_type: node + bundle: person + label: 'Last name' + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: { } + field_type: string + field.field.node.person.profile_image: + uuid: 1b277342-55f9-4a53-8389-c4f05570e4b0 + langcode: en + status: true + dependencies: + config: + - field.storage.node.profile_image + - media.type.image + - node.type.person + _core: + default_config_hash: pYYEZRKCY_nAsQDyVZWbbEdl3FxXXSEiQM3ztrdPrHM + id: node.person.profile_image + field_name: profile_image + entity_type: node + bundle: person + label: 'Profile image' + description: '' + required: false + translatable: false + default_value: { } + default_value_callback: '' + settings: + handler: 'default:media' + handler_settings: + target_bundles: + image: image + sort: + field: _none + direction: ASC + auto_create: false + auto_create_bundle: '' + field_type: entity_reference + field.storage.media.categories: + uuid: 33c3323c-cc16-4f3e-9ca1-4148e24d7c8c + langcode: en + status: true + dependencies: + module: + - media + - taxonomy + _core: + default_config_hash: EMuVBQ75PY6QWCLAWkLxUnNUyR_J6hcSyz6dnEGLmYU + id: media.categories + field_name: categories + entity_type: media + type: entity_reference + settings: + target_type: taxonomy_term + module: core + locked: false + cardinality: -1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.media.media_file: + uuid: 134fb0bd-9f5b-4cf4-93e4-dea848ee6c4c + langcode: en + status: true + dependencies: + module: + - file + - media + id: media.media_file + field_name: media_file + entity_type: media + type: file + settings: + target_type: file + display_field: false + display_default: false + uri_scheme: public + module: file + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.media.media_image: + uuid: 5812e4c8-7d68-475a-9a9b-d0636484dc7c + langcode: en + status: true + dependencies: + module: + - file + - image + - media + id: media.media_image + field_name: media_image + entity_type: media + type: image + settings: + target_type: file + display_field: false + display_default: false + uri_scheme: public + default_image: + uuid: null + alt: '' + title: '' + width: null + height: null + module: image + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.media.media_oembed_video: + uuid: ba80e088-b394-4540-ab44-2f825727584a + langcode: en + status: true + dependencies: + module: + - media + id: media.media_oembed_video + field_name: media_oembed_video + entity_type: media + type: string + settings: + max_length: 255 + case_sensitive: false + is_ascii: false + module: core + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.media.media_video_file: + uuid: 16bbd58a-f1ed-4857-8c25-66ad4690bc2f + langcode: en + status: true + dependencies: + module: + - file + - media + id: media.media_video_file + field_name: media_video_file + entity_type: media + type: file + settings: + target_type: file + display_field: false + display_default: false + uri_scheme: public + module: file + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.media.tags: + uuid: eb2e25c2-1bd9-43c1-b55f-d9fe812c4e51 + langcode: en + status: true + dependencies: + module: + - media + - taxonomy + _core: + default_config_hash: nsDHegRPxHC91wiJ5U-5EJHt7DPaSRwfi_ASFXLmKJ0 + id: media.tags + field_name: tags + entity_type: media + type: entity_reference + settings: + target_type: taxonomy_term + module: core + locked: false + cardinality: -1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.author_profile: + uuid: 0b176e07-472d-48c4-b85c-dc6eaf5f4418 + langcode: en + status: true + dependencies: + module: + - node + _core: + default_config_hash: j6F8e6ZXfehSgEtIgt5RlqvE2u3wEGrQzsePMnFmCJY + id: node.author_profile + field_name: author_profile + entity_type: node + type: entity_reference + settings: + target_type: node + module: core + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.bio: + uuid: 26e37c7e-a149-4806-b76a-accd26fb4313 + langcode: en + status: true + dependencies: + module: + - node + - text + _core: + default_config_hash: cjeVsWv_HNS6yv-LIYKE9GnyDAZn4h9IHSyREZMSnJA + id: node.bio + field_name: bio + entity_type: node + type: text_long + settings: { } + module: text + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.body: + uuid: 4f7870f6-0e18-4a78-8768-2c5b5a979855 + langcode: en + status: true + dependencies: + module: + - node + - text + _core: + default_config_hash: MUIKkjeexJ6Ditr19_dwVpmPBXBMpqyId3UXHlqrlXA + id: node.body + field_name: body + entity_type: node + type: text_with_summary + settings: { } + module: text + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: true + custom_storage: false + field.storage.node.categories: + uuid: 70f9a5f7-ba7f-4b38-b5a9-be475b029982 + langcode: en + status: true + dependencies: + module: + - node + - taxonomy + _core: + default_config_hash: _vzK8VMUJt-ef0dvEzZL8ePpFHT2XHkk7PkVH5gvNOE + id: node.categories + field_name: categories + entity_type: node + type: entity_reference + settings: + target_type: taxonomy_term + module: core + locked: false + cardinality: -1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.cover_image: + uuid: 5ab86e70-c3a4-4f64-8a49-6f670d976aea + langcode: en + status: true + dependencies: + module: + - media + - node + _core: + default_config_hash: Peu21t69lDVGV9QEO06-eV0n8cg9N6EzyRTQ7KZ4Vd4 + id: node.cover_image + field_name: cover_image + entity_type: node + type: entity_reference + settings: + target_type: media + module: core + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.first_name: + uuid: a9e1f580-9e28-45aa-b032-92fe41a19132 + langcode: en + status: true + dependencies: + module: + - node + _core: + default_config_hash: N4idHxzebWKnBwWxyzfl50iY4ptpCXfsMLibUlCXiDw + id: node.first_name + field_name: first_name + entity_type: node + type: string + settings: + max_length: 255 + case_sensitive: false + is_ascii: false + module: core + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.job_title: + uuid: c6ad9cf4-f05f-4cd8-99e6-664c6ce0ed5b + langcode: en + status: true + dependencies: + module: + - node + _core: + default_config_hash: Fy4RJGjHzrbwmCsymSvEN0m-28d_Nggwq7dTFOoceBw + id: node.job_title + field_name: job_title + entity_type: node + type: string + settings: + max_length: 255 + case_sensitive: false + is_ascii: false + module: core + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.last_name: + uuid: 85f0c7f6-4ec1-4aff-a365-799d88baea43 + langcode: en + status: true + dependencies: + module: + - node + _core: + default_config_hash: 16tNQBFfe4YcFj4IYhB8W9tXxWV5DlzLXokG1SZim38 + id: node.last_name + field_name: last_name + entity_type: node + type: string + settings: + max_length: 255 + case_sensitive: false + is_ascii: false + module: core + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.media: + uuid: 323235ac-c805-41fc-885a-3f52b60adcc8 + langcode: en + status: true + dependencies: + module: + - media + - node + _core: + default_config_hash: azt40w38SQY5-AE1YBcqUXi4EMrKmLUJJ915h9NM9iY + id: node.media + field_name: media + entity_type: node + type: entity_reference + settings: + target_type: media + module: core + locked: false + cardinality: -1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.profile_image: + uuid: 31ca357c-141a-41c8-b017-300590cf7649 + langcode: en + status: true + dependencies: + module: + - media + - node + _core: + default_config_hash: FWYb-Gltcu5bYj1Jc5hc_V5jsIlEJVEPfjogRDMTR38 + id: node.profile_image + field_name: profile_image + entity_type: node + type: entity_reference + settings: + target_type: media + module: core + locked: false + cardinality: 1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.related_articles: + uuid: a6ffa49b-11bf-4d0e-86a0-61846fd10d8e + langcode: en + status: true + dependencies: + module: + - node + _core: + default_config_hash: tJ5vXWhmoQkCF_9tfIBzesrfEf8QY_WI2wQiZn8wuzk + id: node.related_articles + field_name: related_articles + entity_type: node + type: entity_reference + settings: + target_type: node + module: core + locked: false + cardinality: -1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + field.storage.node.tags: + uuid: d8473663-8d69-4a2b-a456-bfbd777b20b7 + langcode: en + status: true + dependencies: + module: + - node + - taxonomy + _core: + default_config_hash: 7GUCylaSVOHvvTEKJQjhPmxYisi6rljPaBEw-dfGeg4 + id: node.tags + field_name: tags + entity_type: node + type: entity_reference + settings: + target_type: taxonomy_term + module: core + locked: false + cardinality: -1 + translatable: true + indexes: { } + persist_with_no_fields: false + custom_storage: false + filter.format.canvas_html_block: + uuid: 37f4f0ab-15b2-4ba2-9304-83aa106bedab + langcode: en + status: true + dependencies: + enforced: + module: + - canvas + name: 'Drupal Canvas — Block HTML (locked)' + format: canvas_html_block + weight: 1000 + filters: + filter_html: + id: filter_html + provider: filter + status: true + weight: 0 + settings: + allowed_html: '