Как сделать так, чтобы в самописном модуле в mymodule.module стало возможным видеть и обращаться к глобальным переменным и функциям, видимым из шаблонов? Например, $user, db_update() и т.п.
Это и есть весь модуль. Вызов db_update дает: Fatal error: Call to undefined function db_update() in Z:\home\uberfish.local\www\sites\all\modules\mymodule\mymodule.module on line 8
Ага, ясно.
У вас модуль дёргается в обход бутстрапа.
Объявите коллбек через hook_menu()
И было бы неплохо проверять права-роль пользователя, а то все желающие будут публиковать-депубликовать продукты.
Само собой, в шаблоне проверка роли нужна больше для необходимости отрисовки доп. контролов для админа, а отправить /mymodule/func/updstatus.php?pid=1&rid=1&status=1 сможет любой школьник. Поэтому только в модуль.
С шаблона ноды по событию onclick на input-кнопке вызывается js-функция с ajax-запросом:
Вы в node.tpl.php добавляете input?
Если он не находится внутри формы - это невалидное решение.
Если же вы в шаблоне добавляете html-код формы, то решение неправильное.
Почитатйте про Form API
Кстати, если делать форму правильно, то можно навесить на элементы формы свои ajax-коллбеки, и hook_menu не потребуется.
Через hook_menu - не получилось.
Понял, что иду неправильным путем. Если не трудно, объясните мне цепочку действий для реализации такой схемы:
Шаблон ноды -> Если есть роль, то надо отрисовать форму с input'ом, на onclick которого навешивается js-функция с ajax-запросом на сервер -> На сервере выполняется php-функция, которая совершит манипуляции с БД.
В hook_menu() объявляется путь и функция, которая будет вызываться по GET-запросу по этому пути:
<?php /** * Implements hook_menu(). */ function mymodule_menu() { $items = array(); $items['mymodule/func/updstatus'] = array( 'title' => 'my module callback', 'page callback' => 'mymodule_callback_function', // функция, которая будет вызываться 'access arguments' => array('mymodule callback access'), // права доступа для пользовательской роли 'type' => MENU_CALLBACK, ); return $items; }?>
Соотвественно, право доступа 'mymodule callback access' надо указать в hook_permission()
<?php /** * Implements hook_permission(). */ function mymodule_permission() { $permissions = array( 'mymodule callback access' => array( 'title' => t('Change product status by mymodule'), 'description' => t('Change product status by mymodule'), ), ); return $permissions; }?>
И, разумеется, надо определить сам коллбек:
<?php function mymodule_callback_function() { //something to do }?>
После сброса кеша, при GET-запросе по пути /mymodule/func/updstatus будет либо вызываться функция mymodule_callback_function(), либо будет отдаваться 403 - если у пользователя нет права 'Change product status by mymodule'
Не будет работать по двум причинам:
1. В хук меню надо добавить <?php 'delivery callback' => 'ajax_deliver',?>
2. Там где выводим аяксовый элемент, надо добавить библиотеку <?php drupal_add_library('system', 'drupal.ajax'); ?>
Это если без форм. Если с формой, то да, хук меню не нужен. Но саму форму нужно объявить в отдельной функции, потом в шаблоне или препроцессе вызвать её через drupal_get_form.
А вот это:
«Что касается инпута на странице ноды - самый простой вариант сделать его div'ом чтобы html оставался валидным, разукрасить его под кнопку и навесить js-обработчик на клик.»
полный бред.
Что касается инпута на странице ноды - самый простой вариант сделать его div'ом чтобы html оставался валидным, разукрасить его под кнопку и навесить js-обработчик на клик.
Комментарии
Вы db_update юзаете в шаблонах? Ужас. А с юзером всё просто:
<?php
global $user;
?>
Нет, db_update я не юзаю в шаблонах. Собрался вот только юзать в модуле. Но функция не видна в mymodule.module.
Конструкция
<?php
global $user;
?>
тоже результатов не дала,
<?php
var_dump($user);
?>
возвращает NULL.
Поясните, что вообще означает "функция не видна в mymodule.module"? Звучит немного бредово...
И, ну, наверно примеры Вашего модуля позволят установить ошибку, так что - лучше выкладывайте код с пояснениями.
Например, вот:
<?php
/**
* Update product status.
*/
function mymodule_update_product_status($um_pid, $um_rid, $um_pstatus) {
if ($um_pid && $um_rid):
switch ($um_pstatus) {
case 1:
db_update('commerce_product')
->fields(array('status' => 0))
->condition('product_id', $um_pid)
->execute();
db_update('commerce_product_revision')
->fields(array('status' => 0))
->condition('revision_id', $um_rid)
->execute();
echo '<div class="goods-sold-wrapper">';
echo t('The goods are sold');
echo '</div>';
break;
default:
db_update('commerce_product')
->fields(array('status' => 1))
->condition('product_id', $um_pid)
->execute();
db_update('commerce_product_revision')
->fields(array('status' => 1))
->condition('revision_id', $um_rid)
->execute();
echo '<div class="goods-published-wrapper">';
echo t('The goods are published');
echo '</div>';
break;
}
else:
echo '<div class="goods-published-wrapper">';
echo t('Update error!');
echo '</div>';
endif;
}
?>
Это и есть весь модуль. Вызов db_update дает:
Fatal error: Call to undefined function db_update() in Z:\home\uberfish.local\www\sites\all\modules\mymodule\mymodule.module on line 8
Странно.
db_update() определена в файле database.inc и он должен инклудиться во время бутстрапа
http://cgit.drupalcode.org/drupal/tree/includes/bootstrap.inc?h=7.x#n2730
mymodule_update_product_status() когда и откуда вызывается?
И не проще ли было сделать:
$product->status = FALSE;
commerce_product_save($product);
Цепочка такова (наверняка много чего сделано неправильно).
С шаблона ноды по событию onclick на input-кнопке вызывается js-функция с ajax-запросом:
<?php
$module_path = drupal_get_path('module', 'mymodule');
drupal_add_js($module_path . '/js/updstatus.js');
$updst_param = $pid . "," . $p_revid . "," . $p_status . ",'" . $module_path . "/func/updstatus.php'";
echo '<div class="sell-product">';
echo '<input class="button-sell-product" value="' . t('Selling goods') . '" onclick="sellGoods(' . $updst_param . ')" type="button" />';
?>
Сама js-функция:
nocache = Math.random();
http.open('get', '/' + updstphp + '?pid=' + pid + '&rid=' + rid + '&pstatus=' + pstatus + '&nocache= ' + nocache);
http.onreadystatechange = insertReply;
http.send(null);
}
http - объект XMLHttpRequest. По http-open открывается /mymodule/func/updstatus.php:
<?php
include '../mymodule.module';
$get_pid = intval(filter_input(INPUT_GET, 'pid'));
$get_rid = intval(filter_input(INPUT_GET, 'rid'));
$get_pstatus = (bool) filter_input(INPUT_GET, 'pstatus');
echo '<br/>';
echo 'PID=' . $get_pid . ', RID=' . $get_rid . ', Current PStatus = ' . $get_pstatus;
echo '<br/>';
mymodule_update_product_status($get_pid, $get_rid, $get_pstatus);
?>
Ну и здесь уже и запускаем функцию из модуля.
Ага, ясно.
У вас модуль дёргается в обход бутстрапа.
Объявите коллбек через hook_menu()
И было бы неплохо проверять права-роль пользователя, а то все желающие будут публиковать-депубликовать продукты.
Да, роли проверяются и в шаблоне, и в модуле буду проверять, как только увижу $user.
Спасибо, пробую.
В шаблоне - недостаточно.
Путь /func/updstatus.php - существует независимо от того, выводится он в шаблоне или нет.
Само собой, в шаблоне проверка роли нужна больше для необходимости отрисовки доп. контролов для админа, а отправить /mymodule/func/updstatus.php?pid=1&rid=1&status=1 сможет любой школьник. Поэтому только в модуль.
Вы в node.tpl.php добавляете input?
Если он не находится внутри формы - это невалидное решение.
Если же вы в шаблоне добавляете html-код формы, то решение неправильное.
Почитатйте про Form API
Кстати, если делать форму правильно, то можно навесить на элементы формы свои ajax-коллбеки, и hook_menu не потребуется.
Через hook_menu - не получилось.
Понял, что иду неправильным путем. Если не трудно, объясните мне цепочку действий для реализации такой схемы:
Шаблон ноды -> Если есть роль, то надо отрисовать форму с input'ом, на onclick которого навешивается js-функция с ajax-запросом на сервер -> На сервере выполняется php-функция, которая совершит манипуляции с БД.
В hook_menu() объявляется путь и функция, которая будет вызываться по GET-запросу по этому пути:
<?php
/**
* Implements hook_menu().
*/
function mymodule_menu() {
$items = array();
$items['mymodule/func/updstatus'] = array(
'title' => 'my module callback',
'page callback' => 'mymodule_callback_function', // функция, которая будет вызываться
'access arguments' => array('mymodule callback access'), // права доступа для пользовательской роли
'type' => MENU_CALLBACK,
);
return $items;
}?>
Соотвественно, право доступа 'mymodule callback access' надо указать в hook_permission()
<?php
/**
* Implements hook_permission().
*/
function mymodule_permission() {
$permissions = array(
'mymodule callback access' => array(
'title' => t('Change product status by mymodule'),
'description' => t('Change product status by mymodule'),
),
);
return $permissions;
}?>
И, разумеется, надо определить сам коллбек:
<?php
function mymodule_callback_function() {
//something to do
}?>
После сброса кеша, при GET-запросе по пути /mymodule/func/updstatus будет либо вызываться функция mymodule_callback_function(), либо будет отдаваться 403 - если у пользователя нет права 'Change product status by mymodule'
Не будет работать по двум причинам:
1. В хук меню надо добавить
<?php 'delivery callback' => 'ajax_deliver',?>
2. Там где выводим аяксовый элемент, надо добавить библиотеку
<?php drupal_add_library('system', 'drupal.ajax'); ?>
Это если без форм. Если с формой, то да, хук меню не нужен. Но саму форму нужно объявить в отдельной функции, потом в шаблоне или препроцессе вызвать её через drupal_get_form.
А вот это:
«Что касается инпута на странице ноды - самый простой вариант сделать его div'ом чтобы html оставался валидным, разукрасить его под кнопку и навесить js-обработчик на клик.»
полный бред.
Странно... но заработало.Без delivery callback' => 'ajax_deliver'.
Что касается инпута на странице ноды - самый простой вариант сделать его div'ом чтобы html оставался валидным, разукрасить его под кнопку и навесить js-обработчик на клик.
Andruxa, огромное человеческое спасибо. Разложено по полочкам, что никак не удавалось разложить самому при чтении с англоязычных ресурсов.
Ах, да, чуть не забыл: https://habrahabr.ru/post/164443/
Теперь осталось убрать логику из темплейта, и будет drupal-way.
Почитайте, как можно добавить свой контент с помощью hook_node_view:
https://api.drupal.org/comment/48278#comment-48278