<?php
/**
 * -------------------------------------------------------------------------
 *
 * Модуль для модели Tasks.
 *
 * -------------------------------------------------------------------------
 *
 * Эта модель представляет собой таблицу "tasks" базы данных. А в классе её
 * модуля, реализованного ниже, имеются следующие методы для работы с этой
 * таблицей:
 *
 *     PUBLIC     onInstall    ( $db       )  -->  чтобы произвести необходимые действия при первом запуске приложения
 *     PUBLIC     getStructure (           )  -->  чтобы получить структуру записи для формы редактора в админпанели
 *     PROTECTED  addDemoTasks (           )  -->  чтобы добавить в таблицу демонстрационные записи
 *     PUBLIC     add          (      $row )  -->  чтобы добавить новую запись в таблицу
 *     PUBLIC     getBy        ( $id       )  -->  чтобы извлечь запись по её идентификатору
 *     PUBLIC     findBy       ( $filter   )  -->  чтобы извлечь запись по значению фильтра
 *     PUBLIC     select       (           )  -->  чтобы получить список записей, помеченных активными
 *     PUBLIC     selectAll    (           )  -->  чтобы получить список всех записей независимо от пометки
 *     PUBLIC     remove       ( $id       )  -->  чтобы удалить запись по её идентификатору
 *     PUBLIC     update       ( $id, $row )  -->  чтобы обновить запись по её идентификатору
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Examples / Repost Vacancies
 * @license    GPL-2.0
 *             https://opensource.org/license/gpl-2-0/
 * @copyright  2022 MiMiMi Community
 *             https://mimimi.software/
 *
 * -------------------------------------------------------------------------
 */

    /**
     * ---------------------------------------------------------------------
     *
     * Подключаем из папки ядра фреймворка файл "mimimi.core/Module.php".
     * Там объявлен класс "MimimiModule", являющийся простейшей модульной
     * заготовкой. Этот класс подходит как основа для реализуемого ниже
     * модуля.
     *
     * ---------------------------------------------------------------------
     */

    mimimiInclude ( 'Module.php' );

    /**
     * ---------------------------------------------------------------------
     *
     * Создаём на основе класса той заготовки новый класс, в котором напишем
     * программный код текущего модуля. Обратите внимание как задано имя
     * нового класса - оно сложено из имени класса вышестоящего модуля, то
     * есть "MyMimimiModels", и имени текущего PHP-файла без расширения.
     *
     * ---------------------------------------------------------------------
     */

    class MyMimimiModelsTasks extends MimimiModule {

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Обработчик первого запуска приложения.
         *
         * -----------------------------------------------------------------
         *
         * Вызов этого метода происходит лишь в ситуации, когда файл SQLite3
         * базы данных ещё не существовал и только что создан. Поэтому здесь
         * мы просто создаём таблицу "tasks", описывая желаемую структуру
         * записей. Для понимания этого нюанса обратитесь к файлу:
         *
         *     mimimi.modules/Sqlite/Sqlite.php  -->  метод __construct()
         *                           Sqlite.php  -->  метод autoCreate()
         *
         * Колонки "id", "url_root", "created" используем как технические,
         * полагаясь только на их дефолтные значения. Использование значения
         * по умолчанию для колонки "active" является простейшей защитой от
         * теоретически возможных ошибок неконтролируемого добавления записи
         * с неполным набором колонок в случае кривого кода в алгоритме
         * обработки формы ввода, отсеивающей неизменившиеся поля.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function onInstall ( $db ) {
            $db->exec ( 'CREATE TABLE `tasks` ( `id`            INTEGER           PRIMARY KEY  AUTOINCREMENT,'
                                            . ' `url_root`      VARCHAR(16)       DEFAULT "tasks/",'
                                            . ' `name`          VARCHAR(64),'
                                            . ' `module`        VARCHAR(64),'
                                            . ' `type`          VARCHAR(32),'
                                            . ' `params`        VARCHAR(512),'
                                            . ' `metrics`       VARCHAR(512),'
                                            . ' `filter_name`   VARCHAR(64),'
                                            . ' `filter_value`  VARCHAR(64),'
                                            . ' `source_url`    VARCHAR(512),'
                                            . ' `lifetime`      INTEGER UNSIGNED  DEFAULT 30,'
                                            . ' `tg_chat_id`    VARCHAR(32),'
                                            . ' `max_chat_id`   VARCHAR(32),'
                                            . ' `chat_caption`  VARCHAR(64),'
                                            . ' `active`        BOOLEAN           DEFAULT FALSE,'
                                            . ' `created`       DATETIME          DEFAULT CURRENT_TIMESTAMP )' );
            $this->addDemoTasks ( );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Получить структуру записи для формы редактора в админпанели.
         *
         * -----------------------------------------------------------------
         *
         * Здесь обозначены колонки записи о задании, которые позволено
         * редактировать администратору в форме ввода. Элементы данного
         * массива означают следующее: имя колонки записи, её значение по
         * умолчанию, тип необходимого поля в форме ввода, надпись над полем
         * ввода, дополнительные атрибуты у поля ввода. Для понимания этого
         * нюанса обратитесь к файлу:
         *
         *     repost.vacancies/Themes/default/snippets/task-form.tpl
         *
         * Так как вторая колонка в массиве обозначена типом "select" (это
         * выпадающий список), мы заранее получаем с помощью контроллера
         * Parser список имён его дочерних модулей и передаём в массив как
         * значение по умолчанию для данной колонки. Чтобы админ мог выбрать
         * в форме ввода модуль парсинга, используемый для создаваемого
         * задания.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @return  array
         *
         * -----------------------------------------------------------------
         */

        public function getStructure ( ) {
            $list = $this->app->controllers->parser->listModules ( );
            return [
                [ 'name',         '',          'text',     'Наименование задания',                              'maxlength="64" required autofocus' ],
                [ 'module',       $list,       'select',   'Через какой модуль выполнять',                      'required'                          ],
                [ 'type',         'vacancies', 'text',     'Имя типа извлекаемых данных (параметр для модуля)', 'maxlength="32"'                    ],
                [ 'params',       '',          'textarea', 'Параметры запроса к системе открытых данных',       'maxlength="512"'                   ],
                [ 'filter_value', '',          'text',     'ИД этих данных в фильтре сайта',                    'maxlength="64" required'           ],
                [ 'filter_name',  '',          'text',     'Как называть их в фильтре',                         'maxlength="64" required'           ],
                [ 'lifetime',     30,          'number',   'Через сколько дней удалить спарсенные данные',      'min="1" max="365" required'        ],
                [ 'tg_chat_id',   '',          'text',     'Имя или ИД принимающего канала в Телеграм',         'maxlength="32"'                    ],
                [ 'max_chat_id',  '',          'text',     'Имя или ИД принимающего канала в MAX',              'maxlength="32"'                    ],
                [ 'chat_caption', '',          'text',     'Название кнопки канала, чтобы показать на сайте',   'maxlength="64"'                    ],
                [ 'active',       0,           'number',   'Активно/нет',                                       'min="0" max="1"'                   ],
                [ 'source_url',   '',          'text',     'URL источника в системе открытых данных',           'maxlength="512"'                   ]
            ];
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Добавить демонстрационные задания.
         *
         * -----------------------------------------------------------------
         *
         * Я сделал этот метод для демонстрации только. Дело в том, что
         * когда Вы устанавливаете приложение впервые, то сложно сразу же
         * понять, что требуется писать в каждое из полей формы ввода. А эта
         * запись для вымышленного города Кукуево с неким идентификатором
         * NNNNNNNNNNNNN, появяшаяся автоматически при первом запуске
         * приложения, позволит быстро создать на её основе Ваши реальные
         * задания.
         *
         * Вам лишь надо авторизоваться в админпанели, перейти в список
         * заданий, нажать над карточкой задания кнопку "Копия" и заменить
         * имя города, его идентификатор (вместо NNNNNNNNNNNNN везде в полях
         * формы ввода поставьте ИД своего города, его можно узнать на сайте
         * платформы "Труд всем") и Ваши имена каналов в Телеграм и/или Max,
         * если хотите транслировать вакансии ещё и в мессенджер.
         *
         * -----------------------------------------------------------------
         *
         * @protected
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        protected function addDemoTasks ( ) {
            $crlf = "\r\n";
            $this->add ([ 'name'         => 'Кукуево',
                          'module'       => 'trudvsem',
                          'type'         => 'vacancies',
                          'params'       => 'filter = %7B' . $crlf
                                          . '    %22 districts %22 %3A       %5B %22 NNNNNNNNNNNNN %22 %5D %2C' . $crlf
                                          . '    %22 publishDateTime %22 %3A %5B %22 EXP_1 %22 %5D' . $crlf
                                          . '%7D' . $crlf
                                          . '& orderColumn = PUBLISH_DATE_ASC',
                          'filter_name'  => 'Кукуево',
                          'filter_value' => 'NNNNNNNNNNNNN',
                          'tg_chat_id'   => 'kanal_vakansij_kukuevo_v_telege',
                          'max_chat_id'  => 'kanal_vakansij_kukuevo_v_makse',
                          'chat_caption' => 'Работа в Кукуево',
                          'active'       => FALSE,
                          'source_url'   => 'https://trudvsem.ru/vacancy/search?_regionIds=&_districts=NNNNNNNNNNNNN&page=0&publishDateTime=EXP_1' ]);
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Добавить запись задания.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   array  $row  Массив, индексированный именами колонок сохраняемой записи.
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function add ( $row ) {
            $this->owner->addFor ( 'tasks', $row );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Получить запись задания по его ИД.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   int    $id  Идентификатор запрашиваемой записи.
         * @return  array       Массив, индексированный именами колонок извлечённой записи.
         *
         * -----------------------------------------------------------------
         */

        public function getBy ( $id ) {
            return $this->owner->getByFor ( 'tasks', $id );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Получить запись задания по значению фильтра.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   int    $filter  Фильтр запрашиваемой записи.
         * @return  array           Массив, индексированный именами колонок извлечённой записи.
         *
         * -----------------------------------------------------------------
         */

        public function findBy ( $filter ) {
            return $this->owner->queryRow ( 'SELECT * '
                                          . 'FROM `tasks` '
                                          . 'WHERE `filter_value` = ' . $this->owner->bind ( $filter ) );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Получить список только активных заданий.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @return  array  Массив массивов, индексированных именами колонок извлечённых записей.
         *
         * -----------------------------------------------------------------
         */

        public function select ( ) {
            return $this->owner->queryRows ( 'SELECT * '
                                           . 'FROM `tasks` '
                                           . 'WHERE `active` = 1' );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Получить список всех заданий независимо от их состояния.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @return  array  Массив массивов, индексированных именами колонок извлечённых записей.
         *
         * -----------------------------------------------------------------
         */

        public function selectAll ( ) {
            return $this->owner->selectAllFor ( 'tasks' );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Удалить запись задания по его ИД.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   int   $id  Идентификатор удаляемой записи.
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function remove ( $id ) {
            $this->owner->removeFor ( 'tasks', $id );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Обновить запись задания по его ИД.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   int    $id   Идентификатор обновляемой записи.
         * @param   array  $row  Массив, индексированный именами колонок сохраняемой записи.
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function update ( $id, $row ) {
            $this->owner->updateFor ( 'tasks', $id, $row );
        }
    }
