Доброго всем времени суток!
Увидел просьбу на форуме о возможности отложенной публикации, и решил сделать, заодно изучив возможности расширения функционала второй версии.
Я хочу рассказать вам об этом в виде урока.
Мы будем делать отложенную публикацию только для типа контента "Статьи", думаю на все остальные типы контента можно сделать по аналогии.
У нас будут некоторые ограничения, связанные с движком — отложенные статьи сможет создавать только администратор, либо пользователь с правами администратора и у него не должно быть друзей (ниже объясню почему).
Итак, нам необходимо при добавлении или редактировании статьи указать дату публикации статьи. Что нам для этого нужно?
Нам нужно в форму добавления статьи (и редактирования, что в принципе одно и тоже) добавить два поля — одно признак, что статья отложена, второе — дата, когда статья должна опубликоваться.
Зайдем в административную часть, ТИПЫ КОНТЕНТА — СТАТЬИ — ПОЛЯ
добавим новое поле
Системное имя: seelater
Название поля: Опубликовать позже
Подсказка для поля: пишем что-нибудь по желанию
Тип поля: Флаг
Группа — Создать новую группу: Отложенная публикация вводим именно так как написано, это название будет использовано в скрипте, позже поймете зачем
Также, ставим Доступ для изменения — только группе Администраторы
все остальные поля в форме оставляем как есть
скрины
Итак у нас есть одно поле. В качестве поля для даты публикации будем использовать встроенное поле таблицы date_pub — это поле формата ДАТА без времени, поле со временем нужно добавлять как-то отдельно (в движке отсутствует). Поэтому статья будет опубликована только при наступлении указанной даты.
С полями мы закончили, теперь приступим к самому интересному
Мы будем использовать хуки (hooks) движка, чтобы внедрится в его функционирование. В файле /system/controllers/content/manifest.php добавим все наши хуки, которые мы будем использовать, чтобы движок Инстанта их увидел.
Добавьте в массив следующие строки
'content_articles_form',
'content_articles_after_add',
'content_articles_after_update',
чтобы получилось так:
Здесь, content_articles_form хук для вывода формы добавления или редактирования статьи, соответственно, content_articles_after_add и content_articles_after_update — хуки вызываемые после добавления или редактирования статьи
Рассмотрим первый хук, создайте файл content_articles_form.php в папке /system/controllers/content/hooks со следующим содержимым
Этот хук делает следующее — он сначала получает данные формы ( getSctructure() ) далее, ищет в них группу "Отложенная публикация", а в ней как вы помните уже находится поле флага отложенной записи, и если находит, добавляет к нему поле даты публикации date_pub. Далее, после отработки хука у нас появитсяя форма для ввода данных.
Далее, рассмотрим второй и сразу третий хук
Создайте в той же папке hooks еще два файла: content_articles_after_add.php и content_articles_after_update.php
Содержимое первого
и второго
Веселые названия у классов, да? ну да ладно, это мелочи
Первый хук нужен нам для того, чтобы при добавлении статьи решить — будет статья опубликована сразу, или мы её еще "помурыжим". Смотрим значение поля seelater, если единичка, значит проверяем введенную дату публикации, если она больше сегодняшней — выключаем статью полем is_private, чтобы в activity (лента активности) запись пока не отображалась. Точнее она будет отображаться для друзей добавляющего, но у нашего автора друзей то как бы нет 😊. К сожалению в активити нет статуса "показать только мне" или "никому", поэтому будем вставлять такие вот "костыли". После публикации статьи — is_private станет равно нулю — и статья в активити появится.
Далее, сохраняем статью еще раз, и вызываем хук от activity, соответственно
cmsEventsManager::hook("content_after_add_approve", array('ctype_name'=>$ctype['name'], 'item'=>$item));
либо при редактировании
cmsEventsManager::hook("content_after_update_approve", array('ctype_name'=>$ctype['name'], 'item'=>$item));
Странно, конечно, что результат работы хуков AfterUpdate и AfterAdd далее не используется, разработчик или забыл про него или не заметил (подсказка файлы item_add.php, item_edit.php
строки
cmsEventsManager::hook("content_after_add", $item);
cmsEventsManager::hook("content_{$ctype['name']}_after_add", $item);
или
cmsEventsManager::hook("content_after_update", $item);
cmsEventsManager::hook("content_{$ctype['name']}_after_update", $item);
)
Продолжим, теперь у нас при добавлении или редактировании статья обладает признаком отложенности. Как нам вывести правильно статьи, точнее, как нам не показать раньше времени неопубликованные (по нашему мнению) статьи.
Я предлагаю сильно не задумываться, а воспользоваться датасетами то есть Наборами:
Переходим опять в админку, ТИПЫ КОНТЕНТА — СТАТЬИ — НАБОРЫ
открываем набор ВСЕ
внизу добавляем фильтр по полю "Опубликовать позже" (наш флаг) ставим ему условие "Не заполнено", как на скрине
Тоже самое нужно сделать со всеми остальными наборами, чтобы они ненароком не показали нашу статью.
Что мы уже получили — мы можем не показывать статью до определенной даты. Если нам нужно показать её, мы просто убираем флаг отложенности — и она появляется. Но это вручную, а как сделать так, чтобы статьи публиковались сами.
Воспользуемся крон-задачами. То есть задачами по расписанию. Добавим последний хук в content, он то и будет публиковать наши статьи по наступлении указанной даты.
Итак добавляем файл cron_republic.php в папку /system/controllers/content/hooks (почему не нужно добавлять в manifest.php? сам не знаю, так работает 😊)
Далее заходим в админку — НАСТРОЙКИ — ПЛАНИРОВЩИК — СОЗДАТЬ ЗАДАЧУ и делаем как на скрине
На этом все, отложенная публикация должна работать. Есть только один момент, я не тестировал на хостинге с рабочим кроном, запускал задачу только вручную. Есть некоторые сомнения по поводу работы крон-задачи — нужна проверка. Может быть необходимо делать как-то по другому...
Урок закончен, также можно сделать отложенную публикацию для всех остальных типов контента, либо написав отдельные хуки, либо сделать универсальные.
Напоследок скрин формы добавления статьи
По результатам — как мне показалось, доработки в данной версии Инстанта немного тяжеловаты. Может быть я еще не все в ней понимаю, но поля published в процессе очень не хватало 😊
Увидел просьбу на форуме о возможности отложенной публикации, и решил сделать, заодно изучив возможности расширения функционала второй версии.
Я хочу рассказать вам об этом в виде урока.
Мы будем делать отложенную публикацию только для типа контента "Статьи", думаю на все остальные типы контента можно сделать по аналогии.
У нас будут некоторые ограничения, связанные с движком — отложенные статьи сможет создавать только администратор, либо пользователь с правами администратора и у него не должно быть друзей (ниже объясню почему).
Итак, нам необходимо при добавлении или редактировании статьи указать дату публикации статьи. Что нам для этого нужно?
Нам нужно в форму добавления статьи (и редактирования, что в принципе одно и тоже) добавить два поля — одно признак, что статья отложена, второе — дата, когда статья должна опубликоваться.
Зайдем в административную часть, ТИПЫ КОНТЕНТА — СТАТЬИ — ПОЛЯ
добавим новое поле
Системное имя: seelater
Название поля: Опубликовать позже
Подсказка для поля: пишем что-нибудь по желанию
Тип поля: Флаг
Группа — Создать новую группу: Отложенная публикация вводим именно так как написано, это название будет использовано в скрипте, позже поймете зачем
Также, ставим Доступ для изменения — только группе Администраторы
все остальные поля в форме оставляем как есть
скрины
Итак у нас есть одно поле. В качестве поля для даты публикации будем использовать встроенное поле таблицы date_pub — это поле формата ДАТА без времени, поле со временем нужно добавлять как-то отдельно (в движке отсутствует). Поэтому статья будет опубликована только при наступлении указанной даты.
С полями мы закончили, теперь приступим к самому интересному
Мы будем использовать хуки (hooks) движка, чтобы внедрится в его функционирование. В файле /system/controllers/content/manifest.php добавим все наши хуки, которые мы будем использовать, чтобы движок Инстанта их увидел.
Добавьте в массив следующие строки
'content_articles_form',
'content_articles_after_add',
'content_articles_after_update',
чтобы получилось так:
<?php 'menu_content', 'user_delete', 'user_tab_info', 'user_tab_show', 'sitemap_sources', 'content_articles_form', 'content_articles_after_add', 'content_articles_after_update', ) );
Рассмотрим первый хук, создайте файл content_articles_form.php в папке /system/controllers/content/hooks со следующим содержимым
<?php class onContentContentArticlesForm extends cmsAction { const SEELATERNAME = "Отложенная публикация"; public function run($form){ $structure = $form->getStructure(); // так как по нормальному fieldset выбрать не получится будем искать по title перебором foreach($structure as $ids=>$str) { if ($str['title']==self::SEELATERNAME) { 'title' => 'Дата публикации' ))); break; } } return $form; } }
Далее, рассмотрим второй и сразу третий хук
Создайте в той же папке hooks еще два файла: content_articles_after_add.php и content_articles_after_update.php
Содержимое первого
<?php class onContentContentArticlesAfterAdd extends cmsAction { public function run($item){ if ($item['seelater']==1) { $item['seelater'] = $now < $item['date_pub'] ? 1 : NULL; $item['is_private'] = $item['seelater'] == 1 ? 1 : 0; $ctype = $this->model->getContentTypeByName('articles'); $fields = $this->model->getContentFields($ctype['name'], $item['id']); $item = $this->model->updateContentItem($ctype, $item['id'], $item,$fields); $user = cmsUser::getInstance(); if ($user->is_admin) { cmsEventsManager::hook("content_after_add_approve", array('ctype_name'=>$ctype['name'], 'item'=>$item)); } } return $item; } }
<?php class onContentContentArticlesAfterUpdate extends cmsAction { public function run($item){ if ($item['seelater']==1) { $item['seelater'] = $now < $item['date_pub'] ? 1 : NULL; $item['is_private'] = $item['seelater'] == 1 ? 1 : 0; $ctype = $this->model->getContentTypeByName('articles'); $fields = $this->model->getContentFields($ctype['name'], $item['id']); $item = $this->model->updateContentItem($ctype, $item['id'], $item,$fields); $user = cmsUser::getInstance(); if ($user->is_admin) { cmsEventsManager::hook("content_after_update_approve", array('ctype_name'=>$ctype['name'], 'item'=>$item)); } } return $item; } }
Первый хук нужен нам для того, чтобы при добавлении статьи решить — будет статья опубликована сразу, или мы её еще "помурыжим". Смотрим значение поля seelater, если единичка, значит проверяем введенную дату публикации, если она больше сегодняшней — выключаем статью полем is_private, чтобы в activity (лента активности) запись пока не отображалась. Точнее она будет отображаться для друзей добавляющего, но у нашего автора друзей то как бы нет 😊. К сожалению в активити нет статуса "показать только мне" или "никому", поэтому будем вставлять такие вот "костыли". После публикации статьи — is_private станет равно нулю — и статья в активити появится.
Далее, сохраняем статью еще раз, и вызываем хук от activity, соответственно
cmsEventsManager::hook("content_after_add_approve", array('ctype_name'=>$ctype['name'], 'item'=>$item));
либо при редактировании
cmsEventsManager::hook("content_after_update_approve", array('ctype_name'=>$ctype['name'], 'item'=>$item));
Странно, конечно, что результат работы хуков AfterUpdate и AfterAdd далее не используется, разработчик или забыл про него или не заметил (подсказка файлы item_add.php, item_edit.php
строки
cmsEventsManager::hook("content_after_add", $item);
cmsEventsManager::hook("content_{$ctype['name']}_after_add", $item);
или
cmsEventsManager::hook("content_after_update", $item);
cmsEventsManager::hook("content_{$ctype['name']}_after_update", $item);
)
Продолжим, теперь у нас при добавлении или редактировании статья обладает признаком отложенности. Как нам вывести правильно статьи, точнее, как нам не показать раньше времени неопубликованные (по нашему мнению) статьи.
Я предлагаю сильно не задумываться, а воспользоваться датасетами то есть Наборами:
Переходим опять в админку, ТИПЫ КОНТЕНТА — СТАТЬИ — НАБОРЫ
открываем набор ВСЕ
внизу добавляем фильтр по полю "Опубликовать позже" (наш флаг) ставим ему условие "Не заполнено", как на скрине
Тоже самое нужно сделать со всеми остальными наборами, чтобы они ненароком не показали нашу статью.
Что мы уже получили — мы можем не показывать статью до определенной даты. Если нам нужно показать её, мы просто убираем флаг отложенности — и она появляется. Но это вручную, а как сделать так, чтобы статьи публиковались сами.
Воспользуемся крон-задачами. То есть задачами по расписанию. Добавим последний хук в content, он то и будет публиковать наши статьи по наступлении указанной даты.
Итак добавляем файл cron_republic.php в папку /system/controllers/content/hooks (почему не нужно добавлять в manifest.php? сам не знаю, так работает 😊)
<?php class onContentCronRepublic extends cmsAction { public function run(){ $content_model = cmsCore::getModel('content'); $content_model->filterEqual('seelater', 1); $content_model->filterGTEqual('date_pub', $now); $items = $content_model->getContentItems('articles'); $ctype = $this->model->getContentTypeByName('articles'); foreach($items as $item) { $item['is_private'] = $item['seelater'] == 1 ? 1 : 0; $fields = $this->model->getContentFields($ctype['name'], $item['id']); $item = $this->model->updateContentItem($ctype, $item['id'], $item,$fields); cmsEventsManager::hook("content_after_update_approve", array('ctype_name'=>$ctype['name'], 'item'=>$item)); } } } }
На этом все, отложенная публикация должна работать. Есть только один момент, я не тестировал на хостинге с рабочим кроном, запускал задачу только вручную. Есть некоторые сомнения по поводу работы крон-задачи — нужна проверка. Может быть необходимо делать как-то по другому...
Урок закончен, также можно сделать отложенную публикацию для всех остальных типов контента, либо написав отдельные хуки, либо сделать универсальные.
Напоследок скрин формы добавления статьи
По результатам — как мне показалось, доработки в данной версии Инстанта немного тяжеловаты. Может быть я еще не все в ней понимаю, но поля published в процессе очень не хватало 😊
Реклама #
Ильгиз 10 лет назад #
Май 10 лет назад #
shaman888 10 лет назад #
Ильгиз 10 лет назад #
Raiden 10 лет назад #
Май 10 лет назад #
Ну и вообще, полезная вещь, обязательно воспользуюсь.
Большое спасибо, Крот!
Таня 10 лет назад #
Я конечно все внимательно почитала и поняла, что почти ничего не поняла))
На самом деле, конечно, если бы этот вариант устраивал, то разобралась бы.
Кроту, конечно, спасибо за его попытки, но слишком много костылей.
Первое, то что надо быть только админом, не хочется всех авторов делать админами, к тому же у них не должно быть друзей...
Нет возможности назначать время. Получается что если есть 10 запланированных записей на 7 июня, то все они будут опубликованы в 00:00 ? Очень не удобно, когда нужно чтобы в течении дня выходили статьи, а не сразу все в 12 ночи назначенной даты.
В общем я буду смерено ждать, когда r2 возьмется за дело) Очень надеюсь, что эта функция будет нужным дополнением в instantcms и будет такой же простой и удобной, как сами знаете, где)
Def 10 лет назад #
Крот 10 лет назад #
Хотя, можно было бы изменить ядро и все бы работало - но нам ведь этого не нужно - cms должна помогать расширять функционал, а не ставить ограничения
p.s. в первой ветке, отложенные статьи можно сделать проще. наверное)
lokanaft 10 лет назад #
r2 10 лет назад #
Потому что нет смысла использовать хуки, если файл манифеста системного контроллера все равно будет переписан при обновлении.
Крот 10 лет назад #
но ИМХО странно как-то получается - делать контроллер чтобы хакнуть официально другой
контроллер - хакер
SJen 10 лет назад #
Крот 10 лет назад #
r2 10 лет назад #
вам же не странно что в 1.10.3 делается плагин чтобы добавить функционал куда-либо?
в 2.0 просто нет "плагинов" в терминологии 1.x, их роль выполняют контроллеры (осознанно не использую слово "компоненты")
т.к. при ближайшем рассмотрении разница между "компонентами" и "плагинами" становится очень несущественной
Крот 10 лет назад #
в идеале эта возможность должна быть "из коробки"
lokanaft 10 лет назад #
Raiden 10 лет назад #
webtotma 10 лет назад #
Создаем доп.поле в типе контента - "Дата публикации", связываем с БД.
В шаблоне вывода контента парсим это поле на предмет сравнения с текущей датой. Если <=, то выводим
Если поле не заполнено, то публикуем как обычно.
Крот 10 лет назад #
также еще, статьи будут добавлены в активити, а их там быть не должно
также будут выведены в профиле
в принципе конечно можно, но будет много костылей
webtotma 10 лет назад #
Вообщем встраивать эту возможность надо в движок по дефолту.