Как должен выглядеть хук?

Истинно православный хук. Какой он?

#1 30 апреля 2016 в 18:41
Почитал про инстантправославие. Проникся идеей выноса всех изменений в отдельные файлы и вызов их по хуку.
Теперь хочу выяснить, как это должно выглядеть с точки зрения создателей CMS.
Допустим, возникла потребность в создании хитрого датасета, который никак средствами стандартной модели не сделать. Или потребовалось в определенном типе контента выводить комментарии в другом порядке и в другом шаблоне.
Как в таком случае активировать вышеупомянутый хук?
Просто в системный файл вписывать условие, что если if(something){$this->runExternalHook(filehook, $parametrs -> $tarametrs) ?
Файл с хуком располагается в месте filehook и в нем содержится класс (или не содержится?) и функция, которую активирует данный хук.
Как все это правильно должно выглядеть?
#2 30 апреля 2016 в 18:56

Теперь хочу выяснить, как это должно выглядеть с точки зрения создателей CMS.

HiAndy
Нужно в первую очередь прочитать инстант-православную документацию.

Допустим, возникла потребность в создании хитрого датасета, который никак средствами стандартной модели не сделать.

HiAndy
1. Проверить, нет ли уже в движке хука на нужную вам правку функционала.
2. Если сами не нашли, то поначалу лучше спросить на форуме, описав то, что вы хотите сделать. Например на список датасетов хук есть. Повлиять на выборку записей типа контента — тоже хук есть.

Если в движке нужного вам хука не заложено, то необходимо:

1. Проанализировать, куда наиболее функционально вставить вызов хука, что ему передать и как его назвать максимально универсально, не прицепляясь к вашей идее.
2. Добавить вызов хука в код последовательной или параллельной схемой вызова (см. документацию)
3. Написать нам с предложением внести хук в движок или же прислать пулреквест на гитхабе.

Если по документации что-то непонятно — спрашивайте уточняющие вопросы.
#3 30 апреля 2016 в 19:37

1. Проверить, нет ли уже в движке хука на нужную вам правку функционала.

Fuze
Нет, этого нет и быть не может. Это кроме меня вряд ли кому пригодится.
Для обеспечения спецолимпиады на сайте потребовалось создать в таблице рейтинга новую колонку votedate (время голосования).
После этого создал датасеты "лучшие за день" и "лучшие за вчерашний день". И важно, что именно не дата публикации, а сумма рейтинга проголосовавших за отведенное время имеет значение…
Собственно все работает, но пришлось добавить новую функцию в модель контента:


  1. public function getBest($ctype_name, $dataset)
  2. {
  3. if ($dataset == 'bestweek') {if (date("H")<20)
  4. {
  5. $dfrom = date("Y-m-d H:i:s",mktime(20, 0, 0, date("m") , date("d")-9, date("Y")));
  6. $dto = date("Y-m-d H:i:s",mktime(19, 59, 59, date("m") , date("d"), date("Y")));
  7. }
  8. else
  9. {
  10. $dfrom = date("Y-m-d H:i:s",mktime(20, 0, 0, date("m") , date("d")-7, date("Y")));
  11. $dto = date("Y-m-d H:i:s",mktime(19, 59, 59, date("m") , date("d")+1, date("Y")));
  12. }
  13.  
  14. $sql = "SELECT target_id, SUM(score) as points FROM cms_rating_log WHERE target_subject = 'anec' AND votedate BETWEEN '$dfrom' AND NOW()
  15. GROUP BY target_id ORDER BY points DESC LIMIT 0, 15";
  16. } else {
  17. if (date("H")<20)
  18. {
  19. $dfrom = date("Y-m-d H:i:s",mktime(20, 0, 0, date("m") , date("d")-3, date("Y")));
  20.  
  21. $dto = date("Y-m-d H:i:s",mktime(19, 59, 59, date("m") , date("d")-1, date("Y")));
  22. }
  23. else
  24. {
  25. $dfrom = date("Y-m-d H:i:s",mktime(20, 0, 0, date("m") , date("d")-1, date("Y")));
  26. $dto = date("Y-m-d H:i:s",mktime(19, 59, 59, date("m") , date("d"), date("Y")));
  27. }
  28. $sql="Select target_id, sum(score) as points From cms_rating_log Where votedate Between '$dfrom' And '$dto' Group by target_id Order by points DESC LIMIT 15";
  29. }
  30. $items = array();
  31. $arr = $this->db->query($sql);
  32. while ($joke = mysqli_fetch_assoc($arr)){
  33. global $points;
  34. $id = $joke['target_id'];
  35. $points = $joke['points'];
  36. $table_name = $this->table_prefix . $ctype_name;
  37.  
  38. $this->select('u.nickname', 'user_nickname');
  39.  
  40. $this->join('cms_users', 'u', 'u.id = i.user_id');
  41.  
  42. $this->useCache("content.item.{$ctype_name}");
  43.  
  44. $item = $this->getItemByField($table_name, 'id', $id, function($item, $model){
  45. global $points;
  46. $item['user'] = array(
  47. 'id' => $item['user_id'],
  48. 'nickname' => $item['user_nickname']
  49. );
  50. $item['rating'] = $points;
  51.  
  52.  
  53. return $item;
  54.  
  55. }, 'id');
  56. $items[] = $item;
  57. unset ($points);
  58. }
  59.  
  60. return $items;
  61.  
  62. }
  63.  
  64. }
И условие во фронтенд:

  1. if ($dataset == 'bestyesterday' || $dataset == 'besttoday'){
  2. $items = $this->model->getBest($ctype['name'], $dataset);
  3. $total = 15;} else {
  4. $total = $this->model->getContentItemsCount($ctype['name']);
  5. $items = $this->model->getContentItems($ctype['name']);
  6. }
И вот мне бы хотелось всю эту красоту из системный файлов вынести.
#4 30 апреля 2016 в 19:55
HiAndy, у вас во фронтенде стоит уже два хука перед самыми вашими правками
  1.  
  2. list($ctype, $this->model) = cmsEventsManager::hook('content_list_filter', array($ctype, $this->model));
  3. list($ctype, $this->model) = cmsEventsManager::hook("content_{$ctype['name']}_list_filter", array($ctype, $this->model));
  4.  
Создайте файл этого хука, пропишите его в манифесте и делайте с моделью что хотите.
в начале файла можете прописать ваше условие:
  1.  
  2. <?php
  3.  
  4. class onВашкомпонентContentListFilter extends cmsAction {
  5.  
  6. public function run($data){
  7.  
  8. list($ctype, $model) = $data;
  9.  
  10. if ($dataset == 'bestyesterday' || $dataset == 'besttoday'){ // $dataset можно получить из реквеста
  11.  
  12. $model->orderBy('the_best_of_the_best'); // или что-то типа того
  13. }
  14. return array($ctype, $model);
  15.  

Нет, этого нет и быть не может. Это кроме меня вряд ли кому пригодится.

HiAndy
Fuze имел ввиду что добавить строчку типа этой cmsEventsManager::hook('content_list_filter', array($ctype, $this->model)); в нужном месте, а не всю вашу писанину из под первого спойлера.
#5 30 апреля 2016 в 23:37

Создайте файл этого хука, пропишите его в манифесте и делайте с моделью что хотите.

Loadырь

Но зачем мне тогда городить огород с хуками, если с моделью делать что хочу?
Я и так просто написал условие во фронтенде и допфункцию в модели. У меня и так всё работает.

Как раз спрашивал, как сделать тоже самое, но не внося изменений в системные файлы (в модель).
#6 30 апреля 2016 в 23:51

если с моделью делать что хочу?

HiAndy
Вы не поняли. В хуке и выполняйте свои действия. Хук реализуется от контроллера. Т.е. чтобы сделать хук, нужен контроллер, его обрабатывающий. А к контроллеру модель своя (если нужна).
Соответственно в своей модели вы реализуете метод getBest, а в хуке дополните уже существующие записи своими данными.

($joke = mysqli_fetch_assoc($arr)){

HiAndy
Так делать не нужно. Используйте методы класса БД или модели.

Вообще в целом ваш код будет выполняться долго и весь подход в корне неверный — все перемешано, новый список записей получаете по одной, еще и перезаписывая то, что уже получено. Вам нужно использовать хук content_ВАШТ_ТИП_КОНТЕНТА_before_list, в нем для переданных id получить недостающие данные через конструкцию IN mysql и полученные данные записать в массив.

global лучше не использовать, сделать так:

  1. $item = $this->getItemByField($table_name, 'id', $id, function($item, $model) use($points){
  2. $item['user'] = array(
  3. ..........
#7 1 мая 2016 в 00:01
Спасибо, теперь почти понял.

Так делать не нужно. Используйте методы класса БД или модели.

Fuze

Это тяжелое наследие темного прошлого. Эта функция в данный момент работает на сайте под InstantCMS 1.9. Пять лет работает.

global лучше не использовать, сделать так:

Fuze

Завтра попробую. Еще раз спасибо за помощь! v
Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.