/** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { $new_value = $value; if (is_array($value)) { if (!$value) { throw new MigrateException('Can not lookup without a value.'); } } else { $new_value = array($value); } $new_value = NestedArray::getValue($this->configuration['map'], $new_value, $key_exists); if (!$key_exists) { if (array_key_exists('default_value', $this->configuration)) { if (!empty($this->configuration['bypass'])) { throw new MigrateException('Setting both default_value and bypass is invalid.'); } return $this->configuration['default_value']; } if (empty($this->configuration['bypass'])) { throw new MigrateSkipRowException(); } else { return $value; } } return $new_value; }
/** * Form validation handler for widget elements. * * @param array $element * The form element. * @param array $form_state * The form state. */ public static function validateElement(array $element, FormStateInterface $form_state) { parent::validateElement($element, $form_state); // Massage submitted form values. // Drupal\Core\Field\WidgetBase::submit() expects values as // an array of values keyed by delta first, then by column, while our // widgets return the opposite. if (is_array($element['#value'])) { $values = array_values($element['#value']); } else { $values = array($element['#value']); } // Filter out the 'none' option. Use a strict comparison, because // 0 == 'any string'. $index = array_search('_none', $values, TRUE); if ($index !== FALSE) { unset($values[$index]); } // Transpose selections from field => delta to delta => field. $items = array(); foreach ($values as $value) { $items[] = array($element['#key_column'] => $value); } NestedArray::setValue($form_state['values'], $element['#parents'], $items); }
/** * @implement route_alter_variants * @fast */ static function route_alter_variants() { $alters = []; static::$container = \Drupal::getContainer(); foreach (static::getFiles('/^.+\\.routing\\.yml/i') as $file) { $info = static::yamlDecode($file)['alter_variants'] ?? []; $alters = NestedArray::mergeDeep($alters, $info); } foreach ($alters as $name => $variants) { foreach ($variants as $k => $variant) { if (isset($variant['cache'])) { $variant['controller'] = new CacheController($variant['cache'], $variant['controller']); unset($variant['cache']); } if (isset($variant['redirect'])) { $variant['controller'] = new RedirectController($variant['redirect']); unset($variant['redirect']); } if (isset($variant['error'])) { $variant['controller'] = new ErrorController($variant['error']); unset($variant['error']); } if (is_string($variant)) { $variant = ['controller' => $variant]; } if (isset($variant['controller']) && is_string($variant['controller']) && strpos($variant['controller'], '::') !== FALSE) { $variant['controller'] = explode('::', $variant['controller']); } static::appliesRuleDetect($variant); $variants[$k] = $variant; } $alters[$name] = static::sortByPriority($variants); } return $alters; }
/** * Pre-render callback: Renders a link into #markup. * * Doing so during pre_render gives modules a chance to alter the link parts. * * @param array $element * A structured array whose keys form the arguments to _l(): * - #title: The link text to pass as argument to _l(). * - #url: The URL info either pointing to a route or a non routed path. * - #options: (optional) An array of options to pass to _l() or the link * generator. * * @return array * The passed-in element containing a rendered link in '#markup'. */ public static function preRenderLink($element) { // By default, link options to pass to _l() are normally set in #options. $element += array('#options' => array()); // However, within the scope of renderable elements, #attributes is a valid // way to specify attributes, too. Take them into account, but do not override // attributes from #options. if (isset($element['#attributes'])) { $element['#options'] += array('attributes' => array()); $element['#options']['attributes'] += $element['#attributes']; } // This #pre_render callback can be invoked from inside or outside of a Form // API context, and depending on that, a HTML ID may be already set in // different locations. #options should have precedence over Form API's #id. // #attributes have been taken over into #options above already. if (isset($element['#options']['attributes']['id'])) { $element['#id'] = $element['#options']['attributes']['id']; } elseif (isset($element['#id'])) { $element['#options']['attributes']['id'] = $element['#id']; } // Conditionally invoke self::preRenderAjaxForm(), if #ajax is set. if (isset($element['#ajax']) && !isset($element['#ajax_processed'])) { // If no HTML ID was found above, automatically create one. if (!isset($element['#id'])) { $element['#id'] = $element['#options']['attributes']['id'] = HtmlUtility::getUniqueId('ajax-link'); } $element = static::preRenderAjaxForm($element); } if (!empty($element['#url'])) { $options = NestedArray::mergeDeep($element['#url']->getOptions(), $element['#options']); $element['#markup'] = \Drupal::l($element['#title'], $element['#url']->setOptions($options)); } return $element; }
/** * {@inheritdoc} */ public function normalize($entity, $format = NULL, array $context = array()) { $context += array('account' => NULL, 'included_fields' => NULL); // Create the array of normalized fields, starting with the URI. /** @var $entity \Drupal\Core\Entity\ContentEntityInterface */ $normalized = array('_links' => array('self' => array('href' => $this->getEntityUri($entity)), 'type' => array('href' => $this->linkManager->getTypeUri($entity->getEntityTypeId(), $entity->bundle(), $context)))); // If the fields to use were specified, only output those field values. if (isset($context['included_fields'])) { $fields = array(); foreach ($context['included_fields'] as $field_name) { $fields[] = $entity->get($field_name); } } else { $fields = $entity->getFields(); } foreach ($fields as $field) { // Continue if the current user does not have access to view this field. if (!$field->access('view', $context['account'])) { continue; } $normalized_property = $this->serializer->normalize($field, $format, $context); $normalized = NestedArray::mergeDeep($normalized, $normalized_property); } return $normalized; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL) { $form = parent::buildForm($form, $form_state, $page, $display_variant_id); // Set up the attributes used by a modal to prevent duplication later. $attributes = ['class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 'auto'])]; $add_button_attributes = NestedArray::mergeDeep($attributes, ['class' => ['button', 'button--small', 'button-action']]); if ($this->displayVariant instanceof ConditionVariantInterface) { if ($selection_conditions = $this->displayVariant->getSelectionConditions()) { // Selection conditions. $form['selection_section'] = ['#type' => 'details', '#title' => $this->t('Selection Conditions'), '#open' => TRUE]; $form['selection_section']['add'] = ['#type' => 'link', '#title' => $this->t('Add new selection condition'), '#url' => Url::fromRoute('page_manager.selection_condition_select', ['page' => $this->page->id(), 'display_variant_id' => $this->displayVariant->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['selection_section']['table'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Description'), $this->t('Operations')], '#empty' => $this->t('There are no selection conditions.')]; $form['selection_section']['selection_logic'] = ['#type' => 'radios', '#options' => ['and' => $this->t('All conditions must pass'), 'or' => $this->t('Only one condition must pass')], '#default_value' => $this->displayVariant->getSelectionLogic()]; $form['selection_section']['selection'] = ['#tree' => TRUE]; foreach ($selection_conditions as $selection_id => $selection_condition) { $row = []; $row['label']['#markup'] = $selection_condition->getPluginDefinition()['label']; $row['description']['#markup'] = $selection_condition->summary(); $operations = []; $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.selection_condition_edit', ['page' => $this->page->id(), 'display_variant_id' => $this->displayVariant->id(), 'condition_id' => $selection_id]), 'attributes' => $attributes]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.selection_condition_delete', ['page' => $this->page->id(), 'display_variant_id' => $this->displayVariant->id(), 'condition_id' => $selection_id]), 'attributes' => $attributes]; $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['selection_section']['table'][$selection_id] = $row; } } } return $form; }
public function validateForm(array &$element, array &$form_state, \Payment $payment) { $values = \Drupal\Component\Utility\NestedArray::getValue($form_state['values'], $element['#parents']); if (!empty($values['send_transfer_form'])) { $payment->method_data['send_transfer_form'] = $values['send_transfer_form']; } }
/** * Clear values from upload form element. * * @param array $element * Upload form element. * @param \Drupal\Core\Form\FormStateInterface $form_state * Form state object. */ protected function clearFormValues(array &$element, FormStateInterface $form_state) { // We propagated entities to the other parts of the system. We can now remove // them from our values. $form_state->setValueForElement($element['upload']['fids'], ''); NestedArray::setValue($form_state->getUserInput(), $element['upload']['fids']['#parents'], ''); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, FilterFormat $filter_format = NULL) { // Add AJAX support. $form['#prefix'] = '<div id="video-embed-dialog-form">'; $form['#suffix'] = '</div>'; // Ensure relevant dialog libraries are attached. $form['#attached']['library'][] = 'editor/drupal.editor.dialog'; // Simple URL field and submit button for video URL. $form['video_url'] = ['#type' => 'textfield', '#title' => $this->t('Video URL'), '#required' => TRUE, '#default_value' => $this->getUserInput($form_state, 'video_url')]; // If no settings are found, use the defaults configured in the filter // formats interface. $settings = $this->getUserInput($form_state, 'settings'); if (empty($settings) && ($editor = Editor::load($filter_format->id()))) { $editor_settings = $editor->getSettings(); $plugin_settings = NestedArray::getValue($editor_settings, ['plugins', 'video_embed', 'defaults', 'children']); $settings = $plugin_settings ? $plugin_settings : []; } // Create a settings form from the existing video formatter. $form['settings'] = Video::mockInstance($settings)->settingsForm([], new FormState()); $form['settings']['#type'] = 'fieldset'; $form['settings']['#title'] = $this->t('Settings'); $form['actions'] = ['#type' => 'actions']; $form['actions']['save_modal'] = ['#type' => 'submit', '#value' => $this->t('Save'), '#submit' => [], '#ajax' => ['callback' => '::ajaxSubmit', 'event' => 'click', 'wrapper' => 'video-embed-dialog-form']]; return $form; }
/** * Retrieves Solr-specific data for available data types. * * Returns the data type information for both the default Search API data types * and custom data types defined by hook_search_api_data_type_info(). Names for * default data types are not included, since they are not relevant to the Solr * service class. * * We're adding some extra Solr field information for the default search api * data types (as well as on behalf of a couple contrib field types). The * extra information we're adding is documented in * search_api_solr_hook_search_api_data_type_info(). You can use the same * additional keys in hook_search_api_data_type_info() to support custom * dynamic fields in your indexes with Solr. * * @param string|null $type * (optional) A specific type for which the information should be returned. * Defaults to returning all information. * * @return array|null * If $type was given, information about that type or NULL if it is unknown. * Otherwise, an array of all types. The format in both cases is the same as * for search_api_get_data_type_info(). * * @see search_api_get_data_type_info() * @see search_api_solr_hook_search_api_data_type_info() */ public static function getDataTypeInfo($type = NULL) { $types =& drupal_static(__FUNCTION__); if (!isset($types)) { // Grab the stock search_api data types. /** @var \Drupal\search_api\DataType\DataTypePluginManager $data_type_service */ $data_type_service = \Drupal::service('plugin.manager.search_api.data_type'); $types = $data_type_service->getDefinitions(); // Add our extras for the default search api fields. $types = NestedArray::mergeDeep($types, array('text' => array('prefix' => 't'), 'string' => array('prefix' => 's'), 'integer' => array('prefix' => 'i'), 'decimal' => array('prefix' => 'f'), 'date' => array('prefix' => 'd'), 'duration' => array('prefix' => 'i'), 'boolean' => array('prefix' => 'b'), 'uri' => array('prefix' => 's'), 'tokens' => array('prefix' => 't'))); // Extra data type info. $extra_types_info = array('location' => array('prefix' => 'loc'), 'geohash' => array('prefix' => 'geo')); // For the extra types, only add our extra info if it's already been defined. foreach ($extra_types_info as $key => $info) { if (array_key_exists($key, $types)) { // Merge our extras into the data type info $types[$key] += $info; } } } // Return the info. if (isset($type)) { return isset($types[$type]) ? $types[$type] : NULL; } return $types; }
/** * {@inheritdoc} */ public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL) { /** @var \Drupal\block\BlockInterface[] $entities */ $build = array(); foreach ($entities as $entity) { $entity_id = $entity->id(); $plugin = $entity->getPlugin(); $plugin_id = $plugin->getPluginId(); $base_id = $plugin->getBaseId(); $derivative_id = $plugin->getDerivativeId(); $configuration = $plugin->getConfiguration(); // Create the render array for the block as a whole. // @see template_preprocess_block(). $build[$entity_id] = array('#theme' => 'block', '#attributes' => array(), '#contextual_links' => array('block' => array('route_parameters' => array('block' => $entity->id()))), '#weight' => $entity->get('weight'), '#configuration' => $configuration, '#plugin_id' => $plugin_id, '#base_plugin_id' => $base_id, '#derivative_plugin_id' => $derivative_id, '#id' => $entity->id(), '#block' => $entity); $build[$entity_id]['#configuration']['label'] = String::checkPlain($configuration['label']); // Set cache tags; these always need to be set, whether the block is // cacheable or not, so that the page cache is correctly informed. $build[$entity_id]['#cache']['tags'] = NestedArray::mergeDeepArray(array($this->getCacheTag(), $entity->getCacheTag(), $entity->getListCacheTags(), $plugin->getCacheTags())); if ($plugin->isCacheable()) { $build[$entity_id]['#pre_render'][] = array($this, 'buildBlock'); // Generic cache keys, with the block plugin's custom keys appended // (usually cache context keys like 'cache_context.user.roles'). $default_cache_keys = array('entity_view', 'block', $entity->id(), $entity->language()->getId(), 'cache_context.theme'); $max_age = $plugin->getCacheMaxAge(); $build[$entity_id]['#cache'] += array('keys' => array_merge($default_cache_keys, $plugin->getCacheKeys()), 'bin' => $plugin->getCacheBin(), 'expire' => $max_age === Cache::PERMANENT ? Cache::PERMANENT : REQUEST_TIME + $max_age); } else { $build[$entity_id] = $this->buildBlock($build[$entity_id]); } // Don't run in ::buildBlock() to ensure cache keys can be altered. If an // alter hook wants to modify the block contents, it can append another // #pre_render hook. $this->moduleHandler()->alter(array('block_view', "block_view_{$base_id}"), $build[$entity_id], $plugin); } return $build; }
/** * {@inheritdoc} */ public function alter(&$libraries, &$extension = NULL, &$context2 = NULL) { if ($extension === 'bootstrap') { $provider = $this->theme->getProvider(); if ($assets = $provider->getAssets()) { $libraries['base-theme'] = NestedArray::mergeDeepArray([$assets, $libraries['base-theme']], TRUE); // Add a specific version and theme CSS overrides file. // @todo This should be retrieved by the Provider API. $version = $this->theme->getSetting('cdn_' . $provider->getPluginId() . '_version') ?: Bootstrap::FRAMEWORK_VERSION; $libraries['base-theme']['version'] = $version; $provider_theme = $this->theme->getSetting('cdn_' . $provider->getPluginId() . '_theme') ?: 'bootstrap'; $provider_theme = $provider_theme === 'bootstrap' || $provider_theme === 'bootstrap_theme' ? '' : "-{$provider_theme}"; foreach ($this->theme->getAncestry(TRUE) as $ancestor) { $overrides = $ancestor->getPath() . "/css/{$version}/overrides{$provider_theme}.min.css"; if (file_exists($overrides)) { // Since this uses a relative path to the ancestor from DRUPAL_ROOT, // we must prefix the entire path with / so it doesn't append the // active theme's path (which would duplicate the prefix). $libraries['base-theme']['css']['theme']["/{$overrides}"] = []; break; } } } } }
/** * {@inheritdoc} */ public function normalize($entity, $format = NULL, array $context = array()) { $context += array('account' => NULL, 'included_fields' => NULL); // Create the array of normalized fields, starting with the URI. /** @var $entity \Drupal\Core\Entity\ContentEntityInterface */ $normalized = array('_links' => array('self' => array('href' => $this->getEntityUri($entity)), 'type' => array('href' => $this->linkManager->getTypeUri($entity->getEntityTypeId(), $entity->bundle(), $context)))); // If the fields to use were specified, only output those field values. // Otherwise, output all field values except internal ID. if (isset($context['included_fields'])) { $fields = array(); foreach ($context['included_fields'] as $field_name) { $fields[] = $entity->get($field_name); } } else { $fields = $entity->getFields(); } // Ignore the entity ID and revision ID. $exclude = array($entity->getEntityType()->getKey('id'), $entity->getEntityType()->getKey('revision')); foreach ($fields as $field) { // Continue if this is an excluded field or the current user does not have // access to view it. if (in_array($field->getFieldDefinition()->getName(), $exclude) || !$field->access('view', $context['account'])) { continue; } $normalized_property = $this->serializer->normalize($field, $format, $context); $normalized = NestedArray::mergeDeep($normalized, $normalized_property); } return $normalized; }
public function execute() { $file = $this->getUnaliasedPath($this->configuration['in']); $data = file_exists($file) ? YAML::decode(file_get_contents($file)) : []; $keys = explode('/', $this->configuration['key']); NestedArray::setValue($data, $keys, $this->configuration['value']); file_put_contents($file, YAML::encode($data)); }
/** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) { $editor_settings = $editor->getSettings(); $plugin_settings = NestedArray::getValue($editor_settings, ['plugins', 'video_embed', 'defaults', 'children']); $settings = $plugin_settings ?: []; $form['defaults'] = ['#title' => $this->t('Default Settings'), '#type' => 'fieldset', '#tree' => TRUE, 'children' => Video::mockInstance($settings)->settingsForm([], new FormState())]; return $form; }
/** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); $form['use_admin_theme'] = ['#type' => 'checkbox', '#title' => $this->t('Use admin theme'), '#default_value' => $this->entity->usesAdminTheme()]; $attributes = ['class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 'auto'])]; $add_button_attributes = NestedArray::mergeDeep($attributes, ['class' => ['button', 'button--small', 'button-action']]); $form['context'] = ['#type' => 'details', '#title' => $this->t('Available context'), '#open' => TRUE]; $form['context']['add'] = ['#type' => 'link', '#title' => $this->t('Add new static context'), '#url' => Url::fromRoute('page_manager.static_context_add', ['page' => $this->entity->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['context']['available_context'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Name'), $this->t('Type'), $this->t('Operations')], '#empty' => $this->t('There is no available context.')]; $contexts = $this->entity->getContexts(); foreach ($contexts as $name => $context) { $context_definition = $context->getContextDefinition(); $row = []; $row['label'] = ['#markup' => $context_definition->getLabel()]; $row['machine_name'] = ['#markup' => $name]; $row['type'] = ['#markup' => $context_definition->getDataType()]; // Add operation links if the context is a static context. $operations = []; if ($this->entity->getStaticContext($name)) { $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.static_context_edit', ['page' => $this->entity->id(), 'name' => $name]), 'attributes' => $attributes]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.static_context_delete', ['page' => $this->entity->id(), 'name' => $name]), 'attributes' => $attributes]; } $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['context']['available_context'][$name] = $row; } $form['display_variant_section'] = ['#type' => 'details', '#title' => $this->t('Display variants'), '#open' => TRUE]; $form['display_variant_section']['add_new_page'] = ['#type' => 'link', '#title' => $this->t('Add new display variant'), '#url' => Url::fromRoute('page_manager.display_variant_select', ['page' => $this->entity->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['display_variant_section']['display_variants'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Plugin'), $this->t('Weight'), $this->t('Operations')], '#empty' => $this->t('There are no display variants.'), '#tabledrag' => [['action' => 'order', 'relationship' => 'sibling', 'group' => 'display-variant-weight']]]; foreach ($this->entity->getVariants() as $display_variant_id => $display_variant) { $row = ['#attributes' => ['class' => ['draggable']]]; $row['label']['#markup'] = $display_variant->label(); $row['id']['#markup'] = $display_variant->adminLabel(); $row['weight'] = ['#type' => 'weight', '#default_value' => $display_variant->getWeight(), '#title' => $this->t('Weight for @display_variant display variant', ['@display_variant' => $display_variant->label()]), '#title_display' => 'invisible', '#attributes' => ['class' => ['display-variant-weight']]]; $operations = []; $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.display_variant_edit', ['page' => $this->entity->id(), 'display_variant_id' => $display_variant_id])]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.display_variant_delete', ['page' => $this->entity->id(), 'display_variant_id' => $display_variant_id])]; $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['display_variant_section']['display_variants'][$display_variant_id] = $row; } if ($access_conditions = $this->entity->getAccessConditions()) { $form['access_section_section'] = ['#type' => 'details', '#title' => $this->t('Access Conditions'), '#open' => TRUE]; $form['access_section_section']['add'] = ['#type' => 'link', '#title' => $this->t('Add new access condition'), '#url' => Url::fromRoute('page_manager.access_condition_select', ['page' => $this->entity->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['access_section_section']['access_section'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Description'), $this->t('Operations')], '#empty' => $this->t('There are no access conditions.')]; $form['access_section_section']['access_logic'] = ['#type' => 'radios', '#options' => ['and' => $this->t('All conditions must pass'), 'or' => $this->t('Only one condition must pass')], '#default_value' => $this->entity->getAccessLogic()]; $form['access_section_section']['access'] = ['#tree' => TRUE]; foreach ($access_conditions as $access_id => $access_condition) { $row = []; $row['label']['#markup'] = $access_condition->getPluginDefinition()['label']; $row['description']['#markup'] = $access_condition->summary(); $operations = []; $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.access_condition_edit', ['page' => $this->entity->id(), 'condition_id' => $access_id]), 'attributes' => $attributes]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.access_condition_delete', ['page' => $this->entity->id(), 'condition_id' => $access_id]), 'attributes' => $attributes]; $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['access_section_section']['access_section'][$access_id] = $row; } } return $form; }
/** * Drush execution method. Runs imports on the supplied manifest. */ public function import() { /** @var \Drupal\migrate\MigrateTemplateStorage $template_storage */ $template_storage = \Drupal::service('migrate.template_storage'); $this->setupLegacyDb(); $migration_ids = []; $migrations = []; foreach ($this->migrationList as $migration_info) { if (is_array($migration_info)) { // The migration is stored as the key in the info array. $migration_id = key($migration_info); } else { // If it wasn't an array then the info is just the migration_id. $migration_id = $migration_info; } $template = $template_storage->getTemplateByName($migration_id) ?: []; if (is_array($migration_info)) { // If there is some existing global overrides then we merge them in. if (isset($GLOBALS['config'][$migration_id])) { $migration_info = NestedArray::mergeDeep($GLOBALS['config'][$migration_id], $migration_info); } $migration_info = NestedArray::mergeDeepArray([$template, $migration_info], TRUE); } else { $migration_info = $template; } if ($migration_info) { /** @var \Drupal\migrate\Entity\Migration[] $migrations */ $migrations = \Drupal::service('migrate.migration_builder')->createMigrations([$migration_id => $migration_info]); foreach ($migrations as $migration) { $migration_ids[] = $migration->id(); if (!Migration::load($migration->id())) { $migration->save(); } } // We use these migration_ids to run migrations. If we didn't create // anything we pass it on and this will trigger non-existent migrations // messages or resolved by migration loading. // @todo this can return false positives in the non-existent migration // logic if the builder explicitly returned no results. For example, no // taxonomies will cause some things to be empty. if (!$migrations) { $migration_ids[] = $migration_id; } } } // Load all the migrations at once so they're correctly ordered. foreach (Migration::loadMultiple($migration_ids) as $migration) { $executable = $this->executeMigration($migration); // Store all the migrations for later. $migrations[$migration->id()] = array('executable' => $executable, 'migration' => $migration, 'source' => $migration->get('source'), 'destination' => $migration->get('destination')); } // Warn the user if any migrations were not found. $nonexistent_migrations = array_diff($migration_ids, array_keys($migrations)); if (count($nonexistent_migrations) > 0) { drush_log(dt('The following migrations were not found: @migrations', array('@migrations' => implode(', ', $nonexistent_migrations))), 'warning'); } return $migrations; }
/** * {@inheritdoc} */ public function getViewsData() { $views_data = parent::getViewsData(); if ($this->entityType->id() != 'entity_test') { return $views_data; } $views_data = NestedArray::mergeDeep($views_data, \Drupal::state()->get('entity_test.views_data', [])); return $views_data; }
/** * {@inheritdoc} */ public function __construct(array $config = []) { $default_config = array('verify' => TRUE, 'timeout' => 30, 'headers' => array('User-Agent' => 'Drupal/' . \Drupal::VERSION . ' (+https://www.drupal.org/) ' . static::getDefaultUserAgent())); // The entire config array is merged/configurable to allow Guzzle client // options outside of 'defaults' to be changed, such as 'adapter', or // 'message_factory'. $config = NestedArray::mergeDeep(array('defaults' => $default_config), $config, Settings::get('http_client_config', array())); parent::__construct($config); }
public function validateForm(array &$element, array &$form_state, \Payment $payment) { $values = \Drupal\Component\Utility\NestedArray::getValue($form_state['values'], $element['#parents']); $this->validateValues($element, $values); // Merge in validated fields. foreach (array('issuer', 'credit_card_number', 'secure_code', 'expiry_date') as $key) { $payment->method_data[$key] = $values[$key]; } }
/** * Listener for migration imports. */ public function onMigrateImport(MigrateImportEvent $event) { $migration = $event->getMigration(); $configuration = $migration->getDestinationConfiguration(); $entity_types = NestedArray::getValue($configuration, ['content_translation_update_definitions']); if ($entity_types) { $entity_types = array_intersect_key($this->entityManager->getDefinitions(), array_flip($entity_types)); $this->updateDefinitions($entity_types); } }
/** * {@inheritdoc} */ public function createInstance($plugin_id, array $configuration = []) { // Normally we must never interact with plugins' internal configuration, // but Drupal core's entity reference selection plugins require such // interaction, as they fail to provide APIs for setting required // configuration. See https://www.drupal.org/node/2636322. $default_configuration = ['target_type' => $this->targetEntityTypeId, 'handler_settings' => ['sort' => ['direction' => 'ASC', 'field' => NULL], 'target_bundles' => []]]; $configuration = NestedArray::mergeDeep($default_configuration, $configuration); return parent::createInstance($plugin_id, $configuration); }
/** * Constructs a Plugin object. * * Builds up the plugin definition and invokes the get() method for any * classed annotations that were used. */ public function __construct($values) { $reflection = new \ReflectionClass($this); // Only keep actual default values by ignoring NULL values. $defaults = array_filter($reflection->getDefaultProperties(), function ($value) { return $value !== NULL; }); $parsed_values = $this->parse($values); $this->definition = NestedArray::mergeDeep($defaults, $parsed_values); }
/** * {@inheritdoc} */ protected function initializePlugin($instance_id) { $configuration = $this->manager->getDefinition($instance_id); // Merge the actual configuration into the default configuration. if (isset($this->configurations[$instance_id])) { $configuration = NestedArray::mergeDeep($configuration, $this->configurations[$instance_id]); } $this->configurations[$instance_id] = $configuration; parent::initializePlugin($instance_id); }
/** * Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize() */ public function normalize($field, $format = NULL, array $context = array()) { $normalized_field_items = array(); $entity = $field->getEntity(); $field_name = $field->getName(); $field_definition = $field->getFieldDefinition(); $normalized_field_items = $this->normalizeFieldItems($field, $format, $context); $normalized = NestedArray::mergeDeepArray($normalized_field_items); return $normalized; }
/** * {@inheritdoc} */ public function massageFormValues(array $values, array $form, FormStateInterface $form_state) { $massaged_values = []; foreach ($values as $delta => $item_values) { $element = NestedArray::getValue($form, array_slice($item_values['array_parents'], count($form['#array_parents']))); $plugin_selector = static::getPluginSelector($form_state, $element); $plugin_selector->submitSelectorForm($element['plugin_selector'], $form_state); $massaged_values[$delta] = ['plugin_instance' => $plugin_selector->getSelectedPlugin()]; } return $massaged_values; }
/** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { if (!is_array($value)) { throw new MigrateException('Input should be an array.'); } $new_value = NestedArray::getValue($value, $this->configuration['index'], $key_exists); if (!$key_exists) { throw new MigrateException('Array index missing, extraction failed.'); } return $new_value; }
/** * Constructs the configuration entity dependency from the entity values. * * @param string $name * The configuration entity's configuration object name. * @param array $values * (optional) The configuration entity's values. */ public function __construct($name, $values = []) { $this->name = $name; if (isset($values['dependencies']) && isset($values['dependencies']['enforced'])) { // Merge the enforced dependencies into the list of dependencies. $enforced_dependencies = $values['dependencies']['enforced']; unset($values['dependencies']['enforced']); $this->dependencies = NestedArray::mergeDeep($values['dependencies'], $enforced_dependencies); } elseif (isset($values['dependencies'])) { $this->dependencies = $values['dependencies']; } }
/** * Returns the display objects used to render a set of entities. * * Depending on the configuration of the view mode for each bundle, this can * be either the display object associated to the view mode, or the 'default' * display. * * This method should only be used internally when rendering an entity. When * assigning suggested display options for a component in a given view mode, * entity_get_display() should be used instead, in order to avoid * inadvertently modifying the output of other view modes that might happen to * use the 'default' display too. Those options will then be effectively * applied only if the view mode is configured to use them. * * hook_entity_view_display_alter() is invoked on each display, allowing 3rd * party code to alter the display options held in the display before they are * used to generate render arrays. * * @param \Drupal\Core\Entity\FieldableEntityInterface[] $entities * The entities being rendered. They should all be of the same entity type. * @param string $view_mode * The view mode being rendered. * * @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface[] * The display objects to use to render the entities, keyed by entity * bundle. * * @see entity_get_display() * @see hook_entity_view_display_alter() */ public static function collectRenderDisplays($entities, $view_mode) { if (empty($entities)) { return array(); } // Collect entity type and bundles. $entity_type = current($entities)->getEntityTypeId(); $bundles = array(); foreach ($entities as $entity) { $bundles[$entity->bundle()] = TRUE; } $bundles = array_keys($bundles); // For each bundle, check the existence and status of: // - the display for the view mode, // - the 'default' display. $candidate_ids = array(); foreach ($bundles as $bundle) { if ($view_mode != 'default') { $candidate_ids[$bundle][] = $entity_type . '.' . $bundle . '.' . $view_mode; } $candidate_ids[$bundle][] = $entity_type . '.' . $bundle . '.default'; } $results = \Drupal::entityQuery('entity_view_display')->condition('id', NestedArray::mergeDeepArray($candidate_ids))->condition('status', TRUE)->execute(); // For each bundle, select the first valid candidate display, if any. $load_ids = array(); foreach ($bundles as $bundle) { foreach ($candidate_ids[$bundle] as $candidate_id) { if (isset($results[$candidate_id])) { $load_ids[$bundle] = $candidate_id; break; } } } // Load the selected displays. $storage = \Drupal::entityManager()->getStorage('entity_view_display'); $displays = $storage->loadMultiple($load_ids); $displays_by_bundle = array(); foreach ($bundles as $bundle) { // Use the selected display if any, or create a fresh runtime object. if (isset($load_ids[$bundle])) { $display = $displays[$load_ids[$bundle]]; } else { $display = $storage->create(array('targetEntityType' => $entity_type, 'bundle' => $bundle, 'mode' => $view_mode, 'status' => TRUE)); } // Let the display know which view mode was originally requested. $display->originalMode = $view_mode; // Let modules alter the display. $display_context = array('entity_type' => $entity_type, 'bundle' => $bundle, 'view_mode' => $view_mode); \Drupal::moduleHandler()->alter('entity_view_display', $display, $display_context); $displays_by_bundle[$bundle] = $display; } return $displays_by_bundle; }
/** * Processes AJAX file uploads and deletions. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Drupal\Core\Ajax\AjaxResponse * An AjaxResponse object. */ public function upload(Request $request) { $form_parents = explode('/', $request->query->get('element_parents')); $form_build_id = $request->query->get('form_build_id'); $request_form_build_id = $request->request->get('form_build_id'); if (empty($request_form_build_id) || $form_build_id !== $request_form_build_id) { // Invalid request. drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error'); $response = new AjaxResponse(); $status_messages = array('#theme' => 'status_messages'); return $response->addCommand(new ReplaceCommand(NULL, drupal_render($status_messages))); } try { /** @var $ajaxForm \Drupal\system\FileAjaxForm */ $ajaxForm = $this->getForm($request); $form = $ajaxForm->getForm(); $form_state = $ajaxForm->getFormState(); $commands = $ajaxForm->getCommands(); } catch (HttpExceptionInterface $e) { // Invalid form_build_id. drupal_set_message(t('An unrecoverable error occurred. Use of this form has expired. Try reloading the page and submitting again.'), 'error'); $response = new AjaxResponse(); $status_messages = array('#theme' => 'status_messages'); return $response->addCommand(new ReplaceCommand(NULL, drupal_render($status_messages))); } // Get the current element and count the number of files. $current_element = NestedArray::getValue($form, $form_parents); $current_file_count = isset($current_element['#file_upload_delta']) ? $current_element['#file_upload_delta'] : 0; // Process user input. $form and $form_state are modified in the process. drupal_process_form($form['#form_id'], $form, $form_state); // Retrieve the element to be rendered. $form = NestedArray::getValue($form, $form_parents); // Add the special Ajax class if a new file was added. if (isset($form['#file_upload_delta']) && $current_file_count < $form['#file_upload_delta']) { $form[$current_file_count]['#attributes']['class'][] = 'ajax-new-content'; } else { $form['#suffix'] .= '<span class="ajax-new-content"></span>'; } $status_messages = array('#theme' => 'status_messages'); $form['#prefix'] .= drupal_render($status_messages); $output = drupal_render($form); drupal_process_attached($form); $js = _drupal_add_js(); $settings = drupal_merge_js_settings($js['settings']['data']); $response = new AjaxResponse(); foreach ($commands as $command) { $response->addCommand($command, TRUE); } return $response->addCommand(new ReplaceCommand(NULL, $output, $settings)); }