/**
  * {@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;
 }
 /**
  * {@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;
 }
Example #3
0
 /**
  * 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;
 }
Example #4
0
 /**
  * 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 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;
 }
Example #6
0
 /**
  * @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;
 }
Example #7
0
 /**
  * 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;
 }
Example #8
0
 /**
  * {@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;
 }
Example #9
0
 /**
  * {@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);
 }
Example #10
0
 /**
  * {@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;
 }
Example #11
0
 /**
  * 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);
 }
 /**
  * {@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);
 }
Example #14
0
 /**
  * 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'];
     }
 }
 /**
  * {@inheritdoc}
  */
 protected function initializePlugin($instance_id)
 {
     // Filters have a 1:1 relationship to text formats and can be added and
     // instantiated at any time.
     // @todo $configuration is the whole filter plugin instance configuration,
     //   as contained in the text format configuration. The default
     //   configuration is the filter plugin definition. Configuration should not
     //   be contained in definitions. Move into a FilterBase::init() method.
     $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);
 }
Example #16
0
 /**
  * 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 Drupal::l():
  *   - #title: The link text to pass as argument to Drupal::l().
  *   - One of the following:
  *     - #route_name and (optionally) a #route_parameters array; The route
  *       name and route parameters which will be passed into the link
  *       generator.
  *     - #href: The system path or URL to pass as argument to Drupal::l().
  *   - #options: (optional) An array of options to pass to Drupal::l() or the
  *     link generator.
  *
  * @return array
  *   The passed-in element containing the system compact link default values.
  */
 public static function preRenderCompactLink($element)
 {
     // By default, link options to pass to l() are normally set in #options.
     $element += array('#options' => array());
     if (system_admin_compact_mode()) {
         $element['#title'] = t('Show descriptions');
         $element['#url'] = BaseUrl::fromRoute('system.admin_compact_page', array('mode' => 'off'));
         $element['#options'] = array('attributes' => array('title' => t('Expand layout to include descriptions.')), 'query' => \Drupal::destination()->getAsArray());
     } else {
         $element['#title'] = t('Hide descriptions');
         $element['#url'] = BaseUrl::fromRoute('system.admin_compact_page', array('mode' => 'on'));
         $element['#options'] = array('attributes' => array('title' => t('Compress layout by hiding descriptions.')), 'query' => \Drupal::destination()->getAsArray());
     }
     $options = NestedArray::mergeDeep($element['#url']->getOptions(), $element['#options']);
     $element['#markup'] = \Drupal::l($element['#title'], $element['#url']->setOptions($options));
     return $element;
 }
Example #17
0
 /**
  * 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;
         }
         $migration_ids[] = $migration_id;
         $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::mergeDeep($template, $migration_info);
         } else {
             $migration_info = $template;
         }
         if ($migration_info && !Migration::load($migration_id)) {
             $migration = Migration::create($migration_info);
             $migration->save();
         }
     }
     // Load all the migrations at once so they're correctly ordered.
     foreach (entity_load_multiple('migration', $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;
 }
 /**
  * Update entity browser configuration.
  *
  * @param string $browser
  *   Id of the entity browser.
  * @param array $configuration
  *   Configuration array to update.
  * @param array $oldConfiguration
  *   Only if current config is same like old config we are updating.
  *
  * @return bool
  *   Indicates if config was updated or not.
  */
 public function updateEntityBrowserConfig($browser, $configuration, $oldConfiguration = [])
 {
     $ebConfig = $this->configFactory->getEditable('entity_browser.browser.' . $browser);
     $config = $ebConfig->get();
     if (!empty($oldConfiguration) && DiffArray::diffAssocRecursive($oldConfiguration, $config)) {
         return FALSE;
     }
     $ebConfig->setData(NestedArray::mergeDeep($config, $configuration));
     $ebConfig->save();
     // Update entity browser edit form.
     $entityBrowserConfig = $this->tempStoreFactory->get('entity_browser.config');
     $storage = $entityBrowserConfig->get($browser);
     if (!empty($storage)) {
         foreach ($configuration as $key => $value) {
             $part = $storage['entity_browser']->getPluginCollections()[$key];
             $part->setConfiguration(NestedArray::mergeDeep($part->getConfiguration(), $value));
         }
         $entityBrowserConfig->set($browser, $storage);
     }
     return TRUE;
 }
Example #19
0
 /**
  * {@inheritdoc}
  */
 public function getContainerDefinition()
 {
     $definitions = $this->serviceProviderManager->getDefinitions();
     $container_definition = array();
     $service_providers = array();
     // Populate service providers.
     foreach ($definitions as $plugin_id => $definition) {
         $service_providers[$plugin_id] = $this->serviceProviderManager->createInstance($plugin_id);
     }
     // Get container definition of each service provider and merge them.
     foreach ($definitions as $plugin_id => $definition) {
         $service_provider = $service_providers[$plugin_id];
         $container_definition = NestedArray::mergeDeep($container_definition, $service_provider->getContainerDefinition());
     }
     $container_definition += array('services' => array(), 'parameters' => array());
     // @codeCoverageIgnore
     // Find and setup tags for container altering.
     $container_definition['tags'] = array();
     // Setup the tags structure.
     foreach ($container_definition['services'] as $service => $definition) {
         if (isset($definition['tags'])) {
             foreach ($definition['tags'] as $tag) {
                 $tag_name = $tag['name'];
                 unset($tag['name']);
                 $container_definition['tags'][$tag_name][$service][] = $tag;
             }
         }
     }
     // Ensure container definition can be altered.
     foreach ($definitions as $plugin_id => $definition) {
         $service_provider = $service_providers[$plugin_id];
         $service_provider->alterContainerDefinition($container_definition);
     }
     // Last give a chance for traditional modules to alter this.
     $this->moduleAlter($container_definition);
     // Remove the tags again, not needed for the final build of the container.
     unset($container_definition['tags']);
     return $container_definition;
 }
Example #20
0
 /**
  * {@inheritdoc}
  */
 public function build(array $tree)
 {
     $build = array();
     foreach ($tree as $data) {
         $class = array();
         /** @var \Drupal\Core\Menu\MenuLinkInterface $link */
         $link = $data->link;
         // Generally we only deal with visible links, but just in case.
         if ($link->isHidden()) {
             continue;
         }
         // Set a class for the <li>-tag. Only set 'expanded' class if the link
         // also has visible children within the current tree.
         if ($data->hasChildren && !empty($data->subtree)) {
             $class[] = 'expanded';
         } elseif ($data->hasChildren) {
             $class[] = 'collapsed';
         } else {
             $class[] = 'leaf';
         }
         // Set a class if the link is in the active trail.
         if ($data->inActiveTrail) {
             $class[] = 'active-trail';
         }
         // Allow menu-specific theme overrides.
         $element['#theme'] = 'menu_link__' . strtr($link->getMenuName(), '-', '_');
         $element['#attributes']['class'] = $class;
         $element['#title'] = $link->getTitle();
         $element['#url'] = $link->getUrlObject();
         $element['#below'] = $data->subtree ? $this->build($data->subtree) : array();
         if (isset($data->options)) {
             $element['#url']->setOptions(NestedArray::mergeDeep($element['#url']->getOptions(), $data->options));
         }
         $element['#original_link'] = $link;
         // Index using the link's unique ID.
         $build[$link->getPluginId()] = $element;
     }
     if ($build) {
         // Make sure drupal_render() does not re-order the links.
         $build['#sorted'] = TRUE;
         // Get the menu name from the last link.
         $menu_name = $link->getMenuName();
         // Add the theme wrapper for outer markup.
         // Allow menu-specific theme overrides.
         $build['#theme_wrappers'][] = 'menu_tree__' . strtr($menu_name, '-', '_');
         // Set cache tag.
         $build['#cache']['tags']['menu'][$menu_name] = $menu_name;
     }
     return $build;
 }
Example #21
0
 /**
  * Performs extra processing on plugin definitions.
  *
  * By default we add defaults for the type to the definition. If a type has
  * additional processing logic they can do that by replacing or extending the
  * method.
  */
 public function processDefinition(&$definition, $plugin_id)
 {
     if (!empty($this->defaults) && is_array($this->defaults)) {
         $definition = NestedArray::mergeDeep($this->defaults, $definition);
     }
 }
Example #22
0
 /**
  * {@inheritdoc}
  */
 public function setConfiguration(array $configuration)
 {
     $this->configuration = NestedArray::mergeDeep($this->baseConfigurationDefaults(), $this->defaultConfiguration(), $configuration);
 }
Example #23
0
 /**
  * Performs extra processing on plugin definitions.
  *
  * By default we add defaults for the type to the definition. If a type has
  * additional processing logic, the logic can be added by replacing or
  * extending this method.
  *
  * @param array $definition
  *   The definition to be processed and modified by reference.
  * @param $plugin_id
  *   The ID of the plugin this definition is being used for.
  */
 protected function processDefinition(array &$definition, $plugin_id)
 {
     $definition = NestedArray::mergeDeep($this->defaults, $definition);
     // Typecast so NULL, no parent, will be an empty string since the parent ID
     // should be a string.
     $definition['parent'] = (string) $definition['parent'];
     $definition['id'] = $plugin_id;
 }
Example #24
0
 /**
  * Helper function to mimic \Drupal::moduleHandler()->invokeAll() and include
  * the name of the responding module(s).
  *
  * @param $hook
  *   The name of the hook.
  *
  * @return array
  *   An array of results.
  *   In the case of scalar results, the array is keyed by the name of the
  *   modules that returned the result (rather than by numeric index), and
  *   in the case of array results, a '#module' key is added.
  */
 private static function simulate_module_invoke_all($hook)
 {
     $args = func_get_args();
     // Remove $hook from the arguments.
     array_shift($args);
     $return = array();
     foreach (\Drupal::moduleHandler()->getImplementations($hook) as $module) {
         $function = $module . '_' . $hook;
         $result = call_user_func_array($function, $args);
         if (isset($result)) {
             if (is_array($result)) {
                 foreach ($result as $key => $value) {
                     // Add name of module that returned the value.
                     $result[$key]['#module'] = $module;
                 }
             } else {
                 // Build array with result keyed by $module.
                 $result = array($module => $result);
             }
             $return = \Drupal\Component\Utility\NestedArray::mergeDeep($return, $result);
         }
     }
     return $return;
 }
Example #25
0
 /**
  * {@inheritdoc}
  */
 public function getCacheTags()
 {
     // Even when the menu block renders to the empty string for a user, we want
     // the cache tag for this menu to be set: whenever the menu is changed, this
     // menu block must also be re-rendered for that user, because maybe a menu
     // link that is accessible for that user has been added.
     $tags = array('menu' => array($this->getDerivativeId()));
     return NestedArray::mergeDeep(parent::getCacheTags(), $tags);
 }
 /**
  * Applies the libraries-extend specified by the active theme.
  *
  * This extends the library definitions with the those specified by the
  * libraries-extend specifications for the active theme.
  *
  * @param string $extension
  *   The name of the extension for which library definitions will be extended.
  * @param string $library_name
  *   The name of the library whose definitions is to be extended.
  * @param $library_definition
  *   The library definition to be extended.
  *
  * @return array
  *   The library definition extended as specified by libraries-extend.
  *
  * @throws \Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException
  */
 protected function applyLibrariesExtend($extension, $library_name, $library_definition)
 {
     $libraries_extend = $this->themeManager->getActiveTheme()->getLibrariesExtend();
     if (!empty($libraries_extend["{$extension}/{$library_name}"])) {
         foreach ($libraries_extend["{$extension}/{$library_name}"] as $library_extend_name) {
             if (!is_string($library_extend_name)) {
                 // Only string library names are allowed.
                 throw new InvalidLibrariesExtendSpecificationException('The libraries-extend specification for each library must be a list of strings.');
             }
             list($new_extension, $new_library_name) = explode('/', $library_extend_name, 2);
             $new_libraries = $this->get($new_extension);
             if (isset($new_libraries[$new_library_name])) {
                 $library_definition = NestedArray::mergeDeep($library_definition, $new_libraries[$new_library_name]);
             } else {
                 throw new InvalidLibrariesExtendSpecificationException(sprintf('The specified library "%s" does not exist.', $library_extend_name));
             }
         }
     }
     return $library_definition;
 }
 /**
  * Parses a given library file and allows module to alter it.
  *
  * This method sets the parsed information onto the library property.
  *
  * Library information is parsed from *.libraries.yml files; see
  * editor.library.yml for an example. Every library must have at least one js
  * or css entry. Each entry starts with a machine name and defines the
  * following elements:
  * - js: A list of JavaScript files to include. Each file is keyed by the file
  *   path. An item can have several attributes (like HTML
  *   attributes). For example:
  *   @code
  *   js:
  *     path/js/file.js: { attributes: { defer: true } }
  *   @endcode
  *   If the file has no special attributes, just use an empty object:
  *   @code
  *   js:
  *     path/js/file.js: {}
  *   @endcode
  *   The path of the file is relative to the module or theme directory, unless
  *   it starts with a /, in which case it is relative to the Drupal root. If
  *   the file path starts with //, it will be treated as a protocol-free,
  *   external resource (e.g., //cdn.com/library.js). Full URLs
  *   (e.g., http://cdn.com/library.js) as well as URLs that use a valid
  *   stream wrapper (e.g., public://path/to/file.js) are also supported.
  * - css: A list of categories for which the library provides CSS files. The
  *   available categories are:
  *   - base
  *   - layout
  *   - component
  *   - state
  *   - theme
  *   Each category is itself a key for a sub-list of CSS files to include:
  *   @code
  *   css:
  *     component:
  *       css/file.css: {}
  *   @endcode
  *   Just like with JavaScript files, each CSS file is the key of an object
  *   that can define specific attributes. The format of the file path is the
  *   same as for the JavaScript files.
  * - dependencies: A list of libraries this library depends on.
  * - version: The library version. The string "VERSION" can be used to mean
  *   the current Drupal core version.
  * - header: By default, JavaScript files are included in the footer. If the
  *   script must be included in the header (along with all its dependencies),
  *   set this to true. Defaults to false.
  * - minified: If the file is already minified, set this to true to avoid
  *   minifying it again. Defaults to false.
  * - remote: If the library is a third-party script, this provides the
  *   repository URL for reference.
  * - license: If the remote property is set, the license information is
  *   required. It has 3 properties:
  *   - name: The human-readable name of the license.
  *   - url: The URL of the license file/information for the version of the
  *     library used.
  *   - gpl-compatible: A Boolean for whether this library is GPL compatible.
  *
  * See https://www.drupal.org/node/2274843#define-library for more
  * information.
  *
  * @param string $extension
  *   The name of the extension that registered a library.
  * @param string $path
  *   The relative path to the extension.
  *
  * @return array
  *   An array of parsed library data.
  *
  * @throws \Drupal\Core\Asset\Exception\InvalidLibraryFileException
  *   Thrown when a parser exception got thrown.
  */
 protected function parseLibraryInfo($extension, $path)
 {
     $libraries = [];
     $library_file = $path . '/' . $extension . '.libraries.yml';
     if (file_exists($this->root . '/' . $library_file)) {
         try {
             $libraries = Yaml::decode(file_get_contents($this->root . '/' . $library_file));
         } catch (InvalidDataTypeException $e) {
             // Rethrow a more helpful exception to provide context.
             throw new InvalidLibraryFileException(sprintf('Invalid library definition in %s: %s', $library_file, $e->getMessage()), 0, $e);
         }
     }
     // Allow modules to add dynamic library definitions.
     $hook = 'library_info_build';
     if ($this->moduleHandler->implementsHook($extension, $hook)) {
         $libraries = NestedArray::mergeDeep($libraries, $this->moduleHandler->invoke($extension, $hook));
     }
     // Allow modules to alter the module's registered libraries.
     $this->moduleHandler->alter('library_info', $libraries, $extension);
     $this->themeManager->alter('library_info', $libraries, $extension);
     return $libraries;
 }
Example #28
0
 /**
  * {@inheritdoc}
  */
 public function invokeAll($hook, array $args = array())
 {
     $return = array();
     $implementations = $this->getImplementations($hook);
     foreach ($implementations as $module) {
         $function = $module . '_' . $hook;
         $result = call_user_func_array($function, $args);
         if (isset($result) && is_array($result)) {
             $return = NestedArray::mergeDeep($return, $result);
         } elseif (isset($result)) {
             $return[] = $result;
         }
     }
     return $return;
 }
Example #29
0
 /**
  * {@inheritdoc}
  */
 public function getDependencies()
 {
     $dependencies = $this->dependencies;
     if (isset($dependencies['enforced'])) {
         // Merge the enforced dependencies into the list of dependencies.
         $enforced_dependencies = $dependencies['enforced'];
         unset($dependencies['enforced']);
         $dependencies = NestedArray::mergeDeep($dependencies, $enforced_dependencies);
     }
     return $dependencies;
 }
Example #30
0
 /**
  * Constructs a Migration.
  *
  * @param array $configuration
  *   Plugin configuration.
  * @param string $plugin_id
  *   The plugin ID.
  * @param mixed $plugin_definition
  *   The plugin definition.
  * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager
  *   The migration plugin manager.
  * @param \Drupal\migrate\Plugin\MigratePluginManagerInterface $source_plugin_manager
  *   The source migration plugin manager.
  * @param \Drupal\migrate\Plugin\MigratePluginManagerInterface $process_plugin_manager
  *   The process migration plugin manager.
  * @param \Drupal\migrate\Plugin\MigrateDestinationPluginManager $destination_plugin_manager
  *   The destination migration plugin manager.
  * @param \Drupal\migrate\Plugin\MigratePluginManagerInterface $idmap_plugin_manager
  *   The ID map migration plugin manager.
  */
 public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationPluginManagerInterface $migration_plugin_manager, MigratePluginManagerInterface $source_plugin_manager, MigratePluginManagerInterface $process_plugin_manager, MigrateDestinationPluginManager $destination_plugin_manager, MigratePluginManagerInterface $idmap_plugin_manager)
 {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->migrationPluginManager = $migration_plugin_manager;
     $this->sourcePluginManager = $source_plugin_manager;
     $this->processPluginManager = $process_plugin_manager;
     $this->destinationPluginManager = $destination_plugin_manager;
     $this->idMapPluginManager = $idmap_plugin_manager;
     foreach (NestedArray::mergeDeep($plugin_definition, $configuration) as $key => $value) {
         $this->{$key} = $value;
     }
 }