entity; $metatag_manager = \Drupal::service('metatag.manager'); $form['#ajax_wrapper_id'] = 'metatag-defaults-form-ajax-wrapper'; $ajax = [ 'wrapper' => $form['#ajax_wrapper_id'], 'callback' => '::rebuildForm', ]; $form['#prefix'] = '
'; $form['#suffix'] = '
'; $default_type = NULL; if (!empty($metatag_defaults)) { $default_type = $metatag_defaults->getOriginalId(); } else { $form_state->set('default_type', $default_type); } $token_types = empty($default_type) ? [] : [explode('__', $default_type)[0]]; // Add the token browser at the top. $form += \Drupal::service('metatag.token')->tokenBrowser($token_types); // If this is a new Metatag defaults, then list available bundles. if ($metatag_defaults->isNew()) { $options = $this->getAvailableBundles(); $form['id'] = [ '#type' => 'select', '#title' => t('Type'), '#description' => t('Select the type of default meta tags you would like to add.'), '#options' => $options, '#required' => TRUE, '#default_value' => $default_type, '#ajax' => $ajax + [ 'trigger_as' => [ 'name' => 'select_id_submit', ], ], ]; $form['select_id_submit'] = [ '#type' => 'submit', '#value' => $this->t('Submit'), '#name' => 'select_id_submit', '#ajax' => $ajax, '#attributes' => [ 'class' => ['js-hide'], ], ]; $values = []; } else { $values = $metatag_defaults->get('tags'); } // Add metatag form fields. $form = $metatag_manager->form($values, $form); return $form; } /** * Ajax form submit handler that will return the whole rebuilt form. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @return array * The form structure. */ public function rebuildForm(array &$form, FormStateInterface $form_state) { return $form; } /** * {@inheritdoc} */ protected function actions(array $form, FormStateInterface $form_state) { $actions = parent::actions($form, $form_state); if (isset($actions['delete'])) { $actions['delete']['#access'] = $actions['delete']['#access'] && !in_array($this->entity->id(), MetatagManager::protectedDefaults()); } return $actions; } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { if ($form_state->getTriggeringElement()['#name'] == 'select_id_submit') { $form_state->set('default_type', $form_state->getValue('id')); $form_state->setRebuild(); } else { parent::submitForm($form, $form_state); } } /** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { $metatag_defaults = $this->entity; // Set the label on new defaults. if ($metatag_defaults->isNew()) { $metatag_defaults_id = $form_state->getValue('id'); $type_parts = explode('__', $metatag_defaults_id); $entity_type = $type_parts[0]; $entity_bundle = isset($type_parts[1]) ? $type_parts[1] : NULL; // Get the entity label. $entity_manager = \Drupal::service('entity_type.manager'); $entity_info = $entity_manager->getDefinitions(); $entity_label = (string) $entity_info[$entity_type]->get('label'); if (!is_null($entity_bundle)) { // Get the bundle label. $bundle_manager = \Drupal::service('entity_type.bundle.info'); $bundle_info = $bundle_manager->getBundleInfo($entity_type); $entity_label .= ': ' . $bundle_info[$entity_bundle]['label']; } // Set the label to the config entity. $this->entity->set('label', $entity_label); } // Set tags within the Metatag entity. $tag_manager = \Drupal::service('plugin.manager.metatag.tag'); $tags = $tag_manager->getDefinitions(); $tag_values = []; foreach ($tags as $tag_id => $tag_definition) { if ($form_state->hasValue($tag_id)) { // Some plugins need to process form input before storing it. Hence, we // set it and then get it. $tag = $tag_manager->createInstance($tag_id); $tag->setValue($form_state->getValue($tag_id)); if (!empty($tag->value())) { $tag_values[$tag_id] = $tag->value(); } } } $metatag_defaults->set('tags', $tag_values); $status = $metatag_defaults->save(); switch ($status) { case SAVED_NEW: drupal_set_message($this->t('Created the %label Metatag defaults.', [ '%label' => $metatag_defaults->label(), ])); break; default: drupal_set_message($this->t('Saved the %label Metatag defaults.', [ '%label' => $metatag_defaults->label(), ])); } $form_state->setRedirectUrl($metatag_defaults->toUrl('collection')); } /** * Returns an array of available bundles to override. * * @return array * A list of available bundles as $id => $label. */ protected function getAvailableBundles() { $options = []; $entity_types = $this->getSupportedEntityTypes(); /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager */ $entity_manager = \Drupal::service('entity_type.manager'); /** @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info */ $bundle_info = \Drupal::service('entity_type.bundle.info'); $metatags_defaults_manager = $entity_manager->getStorage('metatag_defaults'); foreach ($entity_types as $entity_type => $entity_label) { if (empty($metatags_defaults_manager->load($entity_type))) { $options[$entity_label][$entity_type] = "$entity_label (Default)"; } $bundles = $bundle_info->getBundleInfo($entity_type); foreach ($bundles as $bundle_id => $bundle_metadata) { $metatag_defaults_id = $entity_type . '__' . $bundle_id; if (empty($metatags_defaults_manager->load($metatag_defaults_id))) { $options[$entity_label][$metatag_defaults_id] = $bundle_metadata['label']; } } } return $options; } /** * Returns a list of supported entity types. * * @return array * A list of available entity types as $machine_name => $label. */ protected function getSupportedEntityTypes() { $entity_types = []; /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager */ $entity_manager = \Drupal::service('entity_type.manager'); // A list of entity types that are not supported. $unsupported_types = [ // Custom blocks. 'block_content', // Comments. 'comment', // Contact messages are the messages submitted on individual contact forms // so obviously shouldn't get meta tags. 'contact_message', // Menu items. 'menu_link_content', // Shortcut items. 'shortcut', ]; // Make a list of supported content types. foreach ($entity_manager->getDefinitions() as $entity_name => $definition) { // Skip some entity types that we don't want to support. if (in_array($entity_name, $unsupported_types)) { continue; } // Identify supported entities. if ($definition instanceof ContentEntityType) { // Only work with entity types that have a list of links, i.e. publicly // viewable. $links = $definition->get('links'); if (!empty($links)) { $entity_types[$entity_name] = $this->getEntityTypeLabel($definition); } } } return $entity_types; } /** * Returns the text label for the entity type specified. * * @param Drupal\Core\Entity\EntityTypeInterface $entityType * The entity type to process. * * @return string * A label. */ protected function getEntityTypeLabel(EntityTypeInterface $entityType) { $label = $entityType->getLabel(); if (is_a($label, 'Drupal\Core\StringTranslation\TranslatableMarkup')) { /** @var \Drupal\Core\StringTranslation\TranslatableMarkup $label */ $label = $label->render(); } return $label; } }