xandeadx.ru Блог музицирующего веб-девелопера

DrupalПоследовательно запустить два Batch-а

Опубликовано в

Если нужно выполнить последовательно два Batch-а и операции второго Batch-а не зависят от результатов первого, то достаточно подряд вызвать batch_set(), а если зависят, то:

function mymodule_myform_submit($form, &$form_state) {
  // Создаём операции для первого batch-а
  $operations = array();
  for ($i = 0; $i < 100; $i++) {
    $operations[] = array('mymodule_first_batch_operation', array());
  }
 
  // В конец добавляем операцию для запуска второго batch-а
  $operations[] = array('mymodule_start_second_batch', array());
 
  // Запускаем первый batch

DrupalКак передать переменную из конструктора Batch в его finished callback

Опубликовано в

Пример передачи значения переменной foo в mymofule_batch_finished():

/**
 * Form submit.
 */
function mymodule_myform_submit($form, &$form_state) {
  ...
  $batch = array(
    'operations' => $operations,
    'finished' => 'mymodule_batch_finished',
    'foo' => 'bar',
  );
 
  batch_set($batch);
}
 
/**
 * Batch finished callback.
 */
function mymodule_batch_finished($success, $results, $operations) {
  $batch_set = _batch_current_set();
  debug($batch_set['foo']);
}

DrupalАвтоматическое удаление устаревших анонимных заказов в статусе "корзина"

Опубликовано в

Drupal Commerce самостоятельно не удаляет устаревшие анонимные заказы в статусе "корзина", что приводит к бессмысленному распуханию таблицы commerce_order.

"Устаревшими" я считаю заказы анонимных пользователей, чьи сессии были удалены сборщиком мусора (по умолчанию это сессии старше 3 дней).

Решаем проблему:

/**
 * Implements hook_cron().
 */
function hook_cron() {
  if (module_exists('commerce_order')) {
    $order_ids = db_select('commerce_order', 'o')
      ->fields('o', array('order_id'))
      ->condition('o.uid', 0)

DrupalДобавить класс определённому элементу перед выполнением ajax запроса

Опубликовано в

Очень часто перед выполнением ajax запроса нужно добавить какому-то элементу определённый класс, а после получения ответа убрать его, чтобы например показать какую-нибудь анимашу, мол keep calm и всё такое.

Реализовать можно с помощью создания собственного типа ajax-прогресса:

(function ($) {
  if (Drupal.ajax) {
    var ajaxBeforeSend = Drupal.ajax.prototype.beforeSend;
    var ajaxSuccess = Drupal.ajax.prototype.success;
    var ajaxError = Drupal.ajax.prototype.error;
 
    Drupal.ajax.prototype.beforeSend = function(xmlhttprequest, options) {

DrupalВысылать письмо при входе администратора с нового браузера

Опубликовано в

Небольшой код, который уведомляет о входе администратора с нового браузера:

/**
 * Implements hook_user_login().
 */
function modulename_user_login(&$edit, $account) {
  if (
    $account->uid == 1 &&
    (empty($account->data['useragent']) || $account->data['useragent'] != md5($_SERVER['HTTP_USER_AGENT']))
  ) {
    $message = 'Дата: ' . date('r') . "\n";
    $message .= 'IP: ' . ip_address() . "\n";
    $message .= 'Host: ' . @gethostbyaddr(ip_address()) . "\n";
    $message .= 'User Agent: ' . $_SERVER['HTTP_USER_AGENT'] . "\n";

DrupalЕжедневно присылать на почту лог PHP ошибок

Опубликовано в

Код раз в день высылает на основную почту список PHP ошибок из watchdog:

/**
 * Implements hook_cron().
 */
function modulename_cron() {
  if (module_exists('dblog') && date('d') != date('d', variable_get('cron_last'))) {
    $last_send = strtotime('-1 day');
    $events = db_query("
      SELECT wid, type, message, variables, timestamp
      FROM {watchdog}
      WHERE type = 'php' AND timestamp >= :last_send
      ORDER BY wid
      LIMIT 100
    ", array(':last_send' => $last_send));
 
    if ($events->rowCount()) {
      $items = array();

DrupalЧиним onclick на ajax кнопках

Опубликовано в

В седьмом друпале есть фантомный баг с ajax кнопками — если попытаться навесить на такую кнопку onclick, то клик не сработает, так как после события mousedown кнопка дизаблится и последующие события не вызываются. Фантомный он потому, что если ответ от сервера придёт очень быстро (например на локальном компьютере где пинг нулевой), то onclick таки выполнится.

Пример проблемного кода:

$form['submit'] = array(
  '#type' => 'submit',
  '#value' => 'Submit',
  '#ajax' => array(
    'wrapper' => '...',
    'callback' => '...',
  ),

DrupalДобавить на страницу данные о товаре в формате JSON-LD

Опубликовано в

Один из способов добавления данных о товаре в формате JSON-LD в head страницы:

/**
 * Implements hook_node_view().
 */
function hook_node_view($node, $view_mode, $langcode) {
  if ($node->type == 'product_display' && $view_mode == 'full') {
    $product_wrap = entity_metadata_wrapper('node', $node)->field_product;
    $product_price = $product_wrap->commerce_price->value();
 
    $jsonld = array(
      '@context' => 'http://schema.org/',
      '@type' => 'Product',
      'name' => $product_wrap->title->value(),
      'sku' => $product_wrap->sku->value(),

DrupalПростая вставка в текст динамического контента (без использования PHP filter)

Опубликовано в

Часто нужно вставить в середину содержимого ноды или блока какой-нибудь контент, сгенерированный с помощью php, например вьюху или переменную. Для решения задачи можно либо вывести контент используя php фильтр, либо сделать str_replace() в preprocess функции, либо накидать простой текстовый фильтр, заменяющий токены [function:function_name] на результат выполнения функции:

/**
 * Implements hook_filter_info().
 */
function modulename_filter_info() {
  $filters['token_function'] = array(
    'title' => t('Replace [function:*] to function result'),