Тема сегодняшнего урока это интеграция сущности с модулем Pathauto. Чтобы решить поставленную задачу, необходимо, чтобы сущность поддерживала токены. Как это сделать читайте в моем предыдущем уроке поддержка токенов для своей сущности в Drupal.
И так, переходим от слов к делу, скачиваем модуль Pathauto, открываем product.info и добавляем зависимость:
dependencies[] = pathauto
Зависимость добавили, теперь открываем product.module и имплементируем хук hook_pathauto():
/**
* Implements hook_pathauto().
*/
function product_pathauto($op) {
if ($op == 'settings') {
$settings = array(
'module' => 'product', // Название модуля.
'groupheader' => t('Product Paths'), // Заголовок группы, который отображается на странице шаблонов pathauto.
'patterndescr' => t('Default path pattern (applies to all products with blank patterns below)'), // Описание группы.
'patterndefault' => 'product/[product:title]', // Шаблон, который используется по умолчанию.
'token_type' => 'product', // Тип токена.
'patternitems' => array(), // В этом массиве хранятся настройки для кажого бандла, их мы добавим ниже.
'batch_update_callback' => 'product_bulk_update_batch_process', // Функция, которая будет срабатывать при массиовом обновлении альясов.
'batch_file' => drupal_get_path('module', 'product') . '/product.pathauto.inc', // Путь к файлу, в котором хранится функция.
);
// Получаем информацию о нашей сущности и делаем возможность настроить шаблон для каждого бандла в отдельности.
$entity_info = entity_get_info('product');
foreach ($entity_info['bundles'] as $bundle_id => $bundle) {
$settings['patternitems'][$bundle_id] = t('Pattern for all @label paths', array('@label' => $bundle['label']));
}
return (object) $settings;
}
}
Далее имплементируем хук hook_path_alias_types(), для того, чтобы в админке стала доступна функция массового удаления альясов этого типа:
/**
* Implements hook_path_alias_types().
*/
function product_path_alias_types() {
$objects['product/'] = t('Products');
return $objects;
}
Теперь напишем служебные функции для сохранения и обновления альясов:
/**
* Update the URL aliases for an individual product.
*
* @param $product
* A product object.
* @param $op
* Operation being performed on the product ('insert', 'update' or 'bulkupdate').
*/
function _product_update_alias($product, $op) {
// Получаем uri продукта.
$uri = product_uri($product);
$product_wrapper = entity_metadata_wrapper('product', $product);
// Получаем машинное имя бандла.
$bundle = $product_wrapper->getBundle();
// Создаем альяс.
module_load_include('inc', 'pathauto');
pathauto_create_alias('product', $op, $uri['path'], array('product' => $product), $bundle);
}
/**
* Update the URL aliases for multiple products.
*
* @param $ids
* An array of product IDs.
* @param $op
* Operation being performed on the products ('insert', 'update' or
* 'bulkupdate').
*/
function _product_update_alias_multiple($ids, $op) {
// Загружаем продукты.
$products = product_load_multiple($ids);
foreach ($products as $product) {
// Обновляем альясы.
_product_update_alias($product, $op);
}
// Выводим сообщение о том, сколько альясов было обновлено.
drupal_set_message(format_plural(count($ids), 'Updated URL alias for 1 product.', 'Updated URL aliases for @count products.'));
}
Служебные функции написали, теперь имплементируем хук hook_entity_insert() для создания нового альяса:
/**
* Implements hook_entity_insert().
*/
function product_entity_insert($entity, $type) {
if ($type == 'product') {
_product_update_alias($entity, 'insert');
}
}
Далее имплементируем хук hook_entity_update() для обновления альяса:
/**
* Implements hook_entity_update().
*/
function product_entity_update($entity, $type) {
if ($type == 'product') {
_product_update_alias($entity, 'update');
}
}
Теперь имплементируем хук hook_entity_delete() для удаления альса вместе с удаляемой сущностью:
/**
* Implements hook_entity_delete().
*/
function product_entity_delete($entity, $type) {
if ($type == 'product') {
$uri = product_uri($entity);
pathauto_entity_path_delete_all('product', $entity, $uri['path']);
}
}
Осталось написать массовое обновление альясов. Создаем файл product.pathauto.inc, его содержимое:
<?php
/**
* @file
* Pathauto integration for Product module.
*
* @ingroup pathauto
*/
/**
* Batch processing callback; Generate aliases for products.
*/
function product_bulk_update_batch_process(&$context) {
if (!isset($context['sandbox']['current'])) {
$context['sandbox']['count'] = 0;
$context['sandbox']['current'] = 0;
}
$query = db_select('product', 'p');
$query->leftJoin('url_alias', 'ua', "CONCAT('product/', p.id) = ua.source");
$query->addField('p', 'id');
$query->isNull('ua.source');
$query->condition('p.id', $context['sandbox']['current'], '>');
$query->orderBy('p.id');
$query->addTag('pathauto_bulk_update');
$query->addMetaData('entity', 'product');
// Получаем количество продуктов для обработки.
if (!isset($context['sandbox']['total'])) {
$context['sandbox']['total'] = $query->countQuery()->execute()->fetchField();
// Если нет продуктов для обработки, то тут же завершаем работу.
if (!$context['sandbox']['total']) {
$context['finished'] = 1;
return;
}
}
$query->range(0, 25);
$ids = $query->execute()->fetchCol();
_product_update_alias_multiple($ids, 'bulkupdate');
$context['sandbox']['count'] += count($ids);
$context['sandbox']['current'] = max($ids);
$context['message'] = t('Updated alias for product @id.', array('@id' => end($ids)));
if ($context['sandbox']['count'] != $context['sandbox']['total']) {
$context['finished'] = $context['sandbox']['count'] / $context['sandbox']['total'];
}
}
Настраиваем в админке шаблоны альясов и дело сделано!