<?php
/**
 * -------------------------------------------------------------------------
 *
 * Модуль субконтроллера Vacancies.
 *
 * -------------------------------------------------------------------------
 *
 * @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' );

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

    class MyMimimiControllersDashboardVacancies extends MimimiModule {

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Маршрутизировать запрос к сопоставленному макету шаблона.
         *
         * -----------------------------------------------------------------
         *
         * Этот метод обслуживает следующие URL-ы:
         *
         *     https://ваш.сайт/vacancies/edit
         *     https://ваш.сайт/vacancies/delete
         *
         * Генерация HTML-кода страницы пройдёт на основе одного из таких
         * макетов:
         *
         *     repost.vacancies/Themes/default/dashboard/vacancies-edit.tpl
         *     repost.vacancies/Themes/default/dashboard/vacancies-delete.tpl
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $url  (необязательный) Относительный URL запрошенной страницы.
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function run ( $url = '' ) {
            if ( $this->owner->hasAdmin ( ) ) {
                $success = '';
                switch ( $url ) {
                    // когда страница "Изменить вакансию"
                    case 'vacancies/edit':
                         $this->app->models->vacancies->removeOld ( );
                         $row = $this->getRequested ( );
                         if ( $row ) {
                             $struct = $this->app->models->vacancies->getStructure ( );
                             $error  = $this->owner->hasForm ( ) ? $this->onUpdate ( $row, $struct, $success )
                                                                 : '';
                             $data   = [ 'success'     => $success ,
                                         'error'       => $error   ,
                                         'button_name' => 'form'   ,
                                         'structure'   => $struct  ,
                                         'row'         => $row     ];
                             $this->owner->render ( 'dashboard/vacancies-edit.tpl', $data );
                             return;
                         }
                         break;
                    // когда страница "Удалить вакансию"
                    case 'vacancies/delete':
                         $this->app->models->vacancies->removeOld ( );
                         $row = $this->getRequested ( );
                         if ( $row ) {
                             if ( $this->owner->hasAgreed ( ) ) {
                                 $error = $this->onRemove ( $row, $success );
                             } else {
                                 $error = $this->owner->hasForm ( ) ? 'Ошибка: Вы не выполнили обязательное действие с флажком ниже!'
                                                                    : '';
                             }
                             $data = [ 'success'     => $success ,
                                       'error'       => $error   ,
                                       'button_name' => 'form'   ,
                                       'row'         => $row     ];
                             $this->owner->render ( 'dashboard/vacancies-delete.tpl', $data );
                             return;
                         }
                         break;
                }
                // иначе запросили неизвестную нам страницу, тогда показываем "Ошибка 404"
                $this->app->controllers->seo->run ( '404' );
                return;
            }
            // иначе это оказался не админ, значит перебрасываем его на страницу "Вход"
            $this->owner->gotoLogin ( );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Получить запись вакансии, запрошенной в URL.
         *
         * -----------------------------------------------------------------
         *
         * Здесь мы с помощью подходящего метода, размещённого в модуле
         * хранителя контроллеров, извлекаем сначала ИД записи, указанный
         * сейчас в URL-e. Затем по этому ИД с помощью модели Vacancoes
         * читаем такую записи из базы данных и отдаём на выход.
         *
         * Перед этим ещё преобразуем значение колонки "content" из JSON
         * строки в точный массив, что был получен в момент парсинга вакансии.
         * А также преобразуем значение колонки "active" из булевого вида в
         * число 1 или 0, так как знаем, что запись отправится далее в шаблон
         * сайта, где редактируемое поле "active" сделано с помощью тега
         * <input type="number">, для которого значение TRUE или FALSE
         * является неверным и потому исказит результат редактирования. За
         * разбором этого нюанса обратитесь к файлам:
         *
         *     repost.vacancies/Models/Vacancies/Vacancies.php  -->  метод getStructure()
         *     repost.vacancies/Themes/default/snippets/vacancy-form.tpl
         *
         * -----------------------------------------------------------------
         *
         * @protected
         * @return  array  Массив, индексированный именами колонок прочитанной записи.
         *
         * -----------------------------------------------------------------
         */

        protected function getRequested ( ) {
            $id  = $this->app->controllers->getItemId ( );
            $row = $id ? $this->app->models->vacancies->getBy ( $id )
                       : [ ];
            if ( $row ) {
                try {
                    $data = @ json_decode ( $row[ 'content' ], TRUE );
                } catch ( Exception $e ) { }
                if ( is_array ( $data ) ) {
                    $row[ 'content' ] = $data;
                }
                $row[ 'active' ] = $row[ 'active' ] ? 1 : 0;
            }
            return $row;
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Обработчик формы редактирования вакансии.
         *
         * -----------------------------------------------------------------
         *
         * В случае успешного редактирования администратор будет принудительно
         * перенаправлен на страницу списка вакансий. В противном случае он
         * останется на той же форме ввода, в которую будет возвращён текст
         * сообщения об ошибке или демо успехе.
         *
         * Исходя из концепции приложения, мы не даём редактировать в записи
         * вакансии что-либо кроме состояния колонки "active".
         *
         * -----------------------------------------------------------------
         */

        protected function onUpdate ( & $previous, $structure, & $success ) {
            $id = mimimiPost ( 'id', 0 );
            if ( $id != $previous[ 'id' ] ) {
                return 'Ошибка: Обнаружена попытка подменить ИД редактируемой записи!';
            }
            $error = '';
            $row   = [ ];
            foreach ( $structure as $struct ) {
                $name  = $struct[ 0 ];
                $value = mimimiPost ( $name, NULL );
                if ( is_null ( $value ) ) {
                    return 'Ошибка: Полученная форма вакансии не соответствует ожидаемой!';
                }
                $value = preg_replace ( '~(^\s+|\s+$)~u', '', $value );
                if ( $previous[ $name ] != $value ) {
                    $previous[ $name ] = $value;
                    if ( ! $error ) {
                        switch ( $name ) {
                            case 'active':
                                 $value = $value ? 1 : 0;
                                 break;
                        }
                        $row[ $name ] = $value;
                    }
                }
            }
            if ( $error ) {
                return $error;
            }
            if ( $row ) {
                if ( $this->owner->isDemo ( ) ) {
                    $success = 'Ок! Но так как Вы сейчас в демо режиме, сайт игнорирует сохранение любых изменений. Чтобы увидеть, как это работает в действительности, скачайте приложение и запустите у себя на сайте, отключив демо режим.';
                    return '';
                }
                if ( $id ) $this->app->models->vacancies->update ( $id, $row );
            }
            $this->gotoList ( );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Обработчик формы удаления вакансии.
         *
         * -----------------------------------------------------------------
         *
         * В случае успешного удаления администратор будет принудительно
         * перенаправлен на страницу списка вакансий. В противном случае он
         * останется на той же форме ввода, в которую будет возвращён текст
         * о демо успехе.
         *
         * Обратите внимание, пост о вакансии также удаляется и из канала
         * в мессенджерах, если был опубликован в момент парсинга вакансии.
         *
         * -----------------------------------------------------------------
         */

        protected function onRemove ( $previous, & $success ) {
            if ( $this->owner->isDemo ( ) ) {
                $success = 'Ок! Но так как Вы сейчас в демо режиме, сайт игнорирует удаление любых записей. Чтобы увидеть, как это работает в действительности, скачайте приложение и запустите у себя на сайте, отключив демо режим.';
                return '';
            }
            $this->app->models->vacancies->remove ( $previous[ 'id' ] );
            if ( $previuos[ 'via_task' ] ) {
                $task = $this->app->models->tasks->getBy ( $previuos[ 'via_task' ] );
                if ( $task ) {
                    if ( $previuos[ 'tg_message_id'  ]
                    ||   $previuos[ 'max_message_id' ] ) {
                        if ( $previuos[ 'tg_message_id' ]
                        &&   $task[     'tg_chat_id'    ] ) {
                            $this->app->views->telegram->remove (
                                $task[     'tg_chat_id'    ],
                                $previuos[ 'tg_message_id' ]
                            );
                        }
                        if ( $previuos[ 'max_message_id' ]
                        &&   $task[     'max_chat_id'    ] ) {
                            $this->app->views->max->remove (
                                $task[     'max_chat_id'    ],
                                $previuos[ 'max_message_id' ]
                            );
                        }
                    }
                }
            }
            $this->gotoList ( );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Метод: Принудительно перебросить на страницу списка вакансий.
         *
         * -----------------------------------------------------------------
         */

        protected function gotoList ( ) {
            $this->owner->redirect ( 'vacancies' );
        }
    }
