Ускоряем форму редактирования материалов (Metatag, Token)


34

В общем, проблема старая и известная. Правда не на всех рейсурсах заметная. При использовании модуля Metatag, на форму редактирования сущностей добавляется вкладка для индивидуального изменения метатегов. И на ней используется браузер токенов. На больших проектах это может здорово утяжелить форму, что приводит к постоянному подвисанию: после открытия формы браузер долго строит форму (из-за большого кол-ва элементов), или очень долго отрабатывает ajax на форме (при добавлении новых значений во множественных полях).
Далее будут приведены несколько способов, как решить данную проблему.

1. Ограничить размер дерева токенов

Для этого есть готовый модуль Token tweaks. Он дает возможность в админке выбрать максимальный уровень вложенности у токенов. Если нет желания ставить модуль, то достаточно в своем модуле добавить один hook:

function MYMODULE_preprocess_token_tree(&$variables) {
  $variables['recursion_limit'] = min(2, $variables['recursion_limit']);
  //где 2 - это требуемый уровень вложенности
}

2. Заменить браузер токенов на тот, что использует AJAX

Для этого есть модуль Fast Token Browser. Он подгружает дерево токенов через AJAX. При его использовании отпадает необходимость в ограничении уровня вложенности. Так что этот модуль рекомендую всем проектам, с большим кол-вом токенов.

Предыдущие методы касались оптимизации работы с деревом токенов, что несомненно улучшает ситуацию с формами редактирования. Но недостаточно ;-) Дело в том, что сам модуль Metatag генерирует довольно большой html. Далее займемся оптимизацией именно модуля Metatag.

3. Оптимизируем вкладку Metatag

Сначала можно зайти в настройки модуля /admin/config/search/metatags/settings и отключить ненужные сущности (если такие конечно-же присутствуют в вашей системе)

Далее отключаем вкладку Metatag с нужных форм (Нет вкладки - нет проблем). Я отключил для всех материалов, терминов и пользователей

/**
 * Изменения на форме редактирования ноды
 */
function MYMODULE_form_node_form_alter(&$form, &$form_state) {
  unset($form['#metatags']);
}

/**
 * Изменения на форме редактирования термина
 */
function MYMODULE_form_taxonomy_form_term_alter(&$form, &$form_state) {
  unset($form['#metatags']);
}

/**
 * Изменения на форме редактирования пользователя
 */
function MYMODULE_form_user_profile_form_alter(&$form, &$form_state) {
  unset($form['#metatags']);
}

Проверяем форму редактирования и наслаждаемся результатом.

А что делать, если возможность индивидуально редактировать метатеги все таки необходима?

Для этого я предлагаю создать отдельную страницу, в которой выведем стандартную форму от модуля Metatag. Вернем редактирование для материалов и терминов (не представляю, зачем она на странице пользователя):
/**
 * Объявляем адреса страниц
 * Implements hook_menu().
 */
function MYMODULE_menu() {
  $items['node/%node/metatags'] = array(
    'title' => 'Edit Metatag',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('MYMODULE_metatag_edit_form', 0, 1),
    'access arguments' => array(0, 1),
    'access callback' => '_MYMODULE_metatag_edit_access',
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
  );

  $items['taxonomy/term/%taxonomy_term/metatags'] = array(
    'title' => 'Edit Metatag',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('MYMODULE_metatag_edit_form', 1, 2),
    'access arguments' => array(1, 2),
    'access callback' => '_MYMODULE_metatag_edit_access',
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
  );
  return $items;
}

/**
 * Включаем тему админки для данных страниц
 * @return array
 */
function MYMODULE_admin_paths() {
  $paths = array(
    'node/*/metatags' => TRUE,
    'taxonomy/term/*/metatags' => TRUE,
  );
  return $paths;
}

/**
 * Доступ к форме редактирования метатегов
 * @param $type
 * @param $entity
 * @return bool
 */
function _MYMODULE_metatag_edit_access($entity_type, $entity){
  //Проверяем доступ пользователя к редактированию метатегов
  if(!user_access('edit meta tags')){
    return FALSE;
  }
 
  //Корректируем entity_type для терминов
  if($entity_type == 'term'){
    $entity_type = 'taxonomy_term';
  }
  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);

  //Проверяем, включена ли поддержка метатегов для данной сущности
  //(смотрим настройки /admin/config/search/metatags/settings)
  if (!metatag_entity_supports_metatags($entity_type, $bundle)) {
    return FALSE;
  }

  return TRUE;
}

//Строим саму форму

/**
 * Форма редактирования метатегов
 * @param $form
 * @param $form_state
 * @return mixed
 */
function MYMODULE_metatag_edit_form($form, &$form_state){
  $entity_type = isset($form_state['build_info']['args'][0]) ? $form_state['build_info']['args'][0] : FALSE;
  $entity = isset($form_state['build_info']['args'][1]) ? $form_state['build_info']['args'][1] : FALSE;

  if($entity_type == 'term'){
    $entity_type = 'taxonomy_term';
  }

  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);

  //Нужно для работы Metatag
  $form['#entity'] = array(
    '#type' => 'value',
    '#value' => $entity,
  );

  $form['entity_type'] = array(
    '#type' => 'value',
    '#value' => $entity_type,
  );

  $form['entity_id'] = array(
    '#type' => 'value',
    '#value' => intval($entity_id),
  );

  $form['bundle'] = array(
    '#type' => 'value',
    '#value' => $bundle,
  );

  $form['revision_id'] = array(
    '#type' => 'value',
    '#value' => intval($revision_id),
  );

  //Пусть модуль Metatag сделает за нас всю работу :-)
  metatag_field_attach_form($entity_type, $entity, $form, $form_state, $langcode);

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
    '#weight' => 1000,
  );

  return $form;
}

//Осталось добавить сохранение метатегов

/**
 * @param $form
 * @param $form_state
 */
function MYMODULE_metatag_edit_form_submit($form, &$form_state){
  $entity_type = isset($form_state['values']['entity_type']) ? $form_state['values']['entity_type'] : FALSE;
  $entity_id = isset($form_state['values']['entity_id']) ? $form_state['values']['entity_id'] : FALSE;
  $bundle = isset($form_state['values']['bundle']) ? $form_state['values']['bundle'] : FALSE;
  $revision_id = isset($form_state['values']['revision_id']) ? $form_state['values']['revision_id'] : FALSE;

  if($entity_type && $entity_id && $bundle){
    metatag_metatags_save($entity_type, $entity_id, $revision_id, $form_state['values']['metatags'], $bundle);
  }
}

Во в принципе и всё, что хотел рассказать. Данный способ не проверялся на других типах сущностей и на многоязычном сайте, так что предлагаю Вам потестить его. И несколько скриншотов с результатом работы:

Drupal Drupal 7 — Статьи пробраузер
Добавить комментарий
Может быть интересно

Данный скрипт поможет пересохранить файлы Excel в csv. Может быть полезно перед отправкой прайсов на хостинг для дальнейшей обработки

5

Порядок действий для установки Solr на сервере с Centos 7

4
Модуль Migrate это фреймворк для миграции (импорта) данных в Drupal из любых источников.
1

Несколько способов как в twig объединить несколько строк в одну

3
Снова возвращаемся к migrate. Довольно удобный фреймворк для импорта данных в Друпал. Один из распространенных форматов источника для импорта - CSV. Поддерживается migrate из коробки. Описание и примеры работы с классом MigrateSourceCSV можно найти на drupal.org.
2