Source of file ScenarioAjax.php

Size: 20,017 Bytes - Last Modified: 2020-10-24T02:46:31+00:00

/home/travis/build/NextDom/nextdom-core/src/Ajax/ScenarioAjax.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
<?php
/* This file is part of Jeedom.
 *
 * Jeedom is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Jeedom is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Jeedom. If not, see <http://www.gnu.org/licenses/>.
 */

namespace NextDom\Ajax;

use NextDom\Enums\AjaxParams;
use NextDom\Enums\Common;
use NextDom\Enums\FoldersAndFilesReferential;
use NextDom\Enums\NextDomObj;
use NextDom\Enums\UserRight;
use NextDom\Exceptions\CoreException;
use NextDom\Helpers\AuthentificationHelper;
use NextDom\Helpers\NextDomHelper;
use NextDom\Helpers\Utils;
use NextDom\Managers\CmdManager;
use NextDom\Managers\EqLogicManager;
use NextDom\Managers\ScenarioElementManager;
use NextDom\Managers\ScenarioExpressionManager;
use NextDom\Managers\ScenarioManager;
use NextDom\Model\Entity\Scenario;

/**
 * Class ScenarioAjax
 * @package NextDom\Ajax
 */
class ScenarioAjax extends BaseAjax
{
    /**
     * @var string
     */
    protected $NEEDED_RIGHTS     = UserRight::USER;
    /**
     * @var bool
     */
    protected $MUST_BE_CONNECTED = true;
    /**
     * @var bool
     */
    protected $CHECK_AJAX_TOKEN = true;

    /**
     * Change scenario state
     *
     * @throws CoreException
     */
    public function changeState()
    {
        $scenario = ScenarioManager::byId(Utils::initInt(AjaxParams::ID));
        if (!is_object($scenario)) {
            throw new CoreException(__('Scénario ID inconnu : ') . Utils::initInt(AjaxParams::ID));
        }
        if (!$scenario->hasRight('x')) {
            throw new CoreException(__('Vous n\'êtes pas autorisé à faire cette action'));
        }
        switch (Utils::init(AjaxParams::STATE)) {
            default:
            case 'start':
                if (!$scenario->getIsActive()) {
                    throw new CoreException(__('Impossible de lancer le scénario car il est désactivé. Veuillez l\'activer'));
                }
                $scenario->launch('user', 'Scénario lancé manuellement', 0);
                break;
            case 'stop':
                $scenario->stop();
                break;
            case 'deactivate':
                $scenario->setIsActive(0);
                $scenario->save();
                break;
            case 'activate':
                $scenario->setIsActive(1);
                $scenario->save();
                break;
        }
        $this->ajax->success();
    }

    /**
     * @throws \Exception
     */
    public function listScenarioHtml()
    {
        $return = [];
        foreach (ScenarioManager::all() as $scenario) {
            if ($scenario->isVisible()) {
                $return[] = $scenario->toHtml(Utils::init(AjaxParams::VERSION));
            }
        }
        $this->ajax->success($return);
    }

    /**
     * @throws CoreException
     * @throws \ReflectionException
     */
    public function setOrder()
    {
        $scenarios = json_decode(Utils::init(AjaxParams::SCENARIOS), true);
        foreach ($scenarios as $scenario_json) {
            if (!isset($scenario_json[AjaxParams::ID]) || trim($scenario_json[AjaxParams::ID]) == '') {
                continue;
            }
            $scenario = ScenarioManager::byId($scenario_json[AjaxParams::ID]);
            if (!is_object($scenario)) {
                continue;
            }
            Utils::a2o($scenario, $scenario_json);
            $scenario->save();
        }
        $this->ajax->success();
    }

    /**
     * @throws CoreException
     * @throws \ReflectionException
     */
    public function testExpression()
    {
        $result = [];
        $scenario = null;
        $result['evaluate'] = ScenarioExpressionManager::setTags(NextDomHelper::fromHumanReadable(Utils::init(AjaxParams::EXPRESSION)), $scenario, true);
        $result['result'] = Utils::evaluate($result['evaluate']);
        $result['correct'] = 'ok';
        if (trim($result['result']) == trim($result['evaluate'])) {
            $result['correct'] = 'nok';
        }
        $this->ajax->success($result);
    }

    /**
     *
     */
    public function getTemplate()
    {
        $this->ajax->success(ScenarioManager::getTemplate());
    }

    /**
     * Convert current scenario to template
     * @throws CoreException
     */
    public function convertToTemplate()
    {
        $scenario = ScenarioManager::byId(Utils::initInt(AjaxParams::ID));
        if (!is_object($scenario)) {
            throw new CoreException(__('Scénario ID inconnu : ') . Utils::initInt(AjaxParams::ID));
        }
        $path = NEXTDOM_DATA . '/data/scenario';
        if (!file_exists($path)) {
            mkdir($path);
        }
        $template = trim(Utils::initFilename(AjaxParams::TEMPLATE));
        if ($template == '' || $template == '.json') {
            throw new CoreException(__('Le nom du template ne peut être vide '));
        }
        file_put_contents($path . '/' . $template, json_encode($scenario->export('array'), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
        if (!file_exists($path . '/' . $template)) {
            throw new CoreException(__('Impossible de créer le template, vérifiez les droits : ') . $path . '/' . $template);
        }
        $this->ajax->success();
    }

    /**
     *
     */
    public function removeTemplate()
    {
        $templateFile = FoldersAndFilesReferential::SCENARIO_TEMPLATE_FORLDER . Utils::initFilename(AjaxParams::TEMPLATE);
        if (file_exists($templateFile)) {
            unlink($templateFile);
        }
        $this->ajax->success();
    }

    /**
     * @throws CoreException
     */
    public function loadTemplateDiff()
    {
        $templateFile = FoldersAndFilesReferential::SCENARIO_TEMPLATE_FORLDER . Utils::initFilename(AjaxParams::TEMPLATE);
        if (!file_exists($templateFile)) {
            throw new CoreException(__('Fichier non trouvé : ') . $templateFile);
        }
        $result = [];
        foreach (preg_split("/((\r?\n)|(\r\n?))/", file_get_contents($templateFile)) as $line) {
            preg_match_all("/#\[(.*?)\]\[(.*?)\]\[(.*?)\]#/", $line, $matches, PREG_SET_ORDER);
            if (count($matches) > 0) {
                foreach ($matches as $match) {
                    $result[$match[0]] = '';
                    $cmd = null;
                    try {
                        $cmd = CmdManager::byString($match[0]);
                        if (is_object($cmd)) {
                            $result[$match[0]] = '#' . $cmd->getHumanName() . '#';
                        }
                    } catch (\Exception $e) {

                    }
                }
            }
            preg_match_all("/#\[(.*?)\]\[(.*?)\]#/", $line, $matches, PREG_SET_ORDER);
            if (count($matches) > 0) {
                foreach ($matches as $match) {
                    $result[$match[0]] = '';
                    try {
                        $eqLogic = EqLogicManager::byString($match[0]);
                        if (is_object($eqLogic)) {
                            $result[$match[0]] = '#' . $eqLogic->getHumanName() . '#';
                        }
                    } catch (\Exception $e) {

                    }
                }
            }
            preg_match_all("/variable\((.*?)\)/", $line, $matches, PREG_SET_ORDER);
            if (count($matches) > 0) {
                foreach ($matches as $match) {
                    $result[$match[1]] = $match[1];
                }
            }
        }
        $this->ajax->success($result);
    }

    /**
     * @throws CoreException
     * @throws \ReflectionException
     */
    public function applyTemplate()
    {
        $templateFile = FoldersAndFilesReferential::SCENARIO_TEMPLATE_FORLDER . Utils::initFilename(AjaxParams::TEMPLATE);
        if (!file_exists($templateFile)) {
            throw new CoreException(__('Fichier non trouvé : ') . $templateFile);
        }
        $converts = [];
        foreach (json_decode(Utils::init('convert'), true) as $value) {
            if (Utils::init('newValues') == '1') {
                if (trim($value['end']) == '') {
                    throw new CoreException(__('La conversion suivante ne peut pas être vide : ') . $value['begin']);
                }
                $converts[$value['begin']] = $value['end'];
            } else {
                $converts[$value['begin']] = $value['begin'];
            }
        }
        $content = str_replace(array_keys($converts), $converts, file_get_contents($templateFile));
        $scenario_ajax = json_decode($content, true);
        if (isset($scenario_ajax[Common::NAME])) {
            unset($scenario_ajax[Common::NAME]);
        }
        if (isset($scenario_ajax[Common::GROUP])) {
            unset($scenario_ajax[Common::GROUP]);
        }
        $scenario_db = ScenarioManager::byId(Utils::initInt(AjaxParams::ID));
        if (!is_object($scenario_db)) {
            throw new CoreException(__('Scénario ID inconnu : ') . Utils::initInt(AjaxParams::ID));
        }
        if (!$scenario_db->hasRight('w')) {
            throw new CoreException(__('Vous n\'êtes pas autorisé à faire cette action'));
        }
        $scenario_db->setTrigger([]);
        $scenario_db->setSchedule([]);
        Utils::a2o($scenario_db, $scenario_ajax);
        $scenario_db->save();
        $scenario_element_list = [];
        if (isset($scenario_ajax['elements'])) {
            foreach ($scenario_ajax['elements'] as $element_ajax) {
                $scenario_element_list[] = ScenarioElementManager::saveAjaxElement($element_ajax);
            }
            $scenario_db->setScenarioElement($scenario_element_list);
        }
        $scenario_db->save();
        $this->ajax->success();
    }

    /**
     * @throws \ReflectionException
     */
    public function all()
    {
        $scenarios = ScenarioManager::all();
        $result = [];
        foreach ($scenarios as $scenario) {
            $info_scenario = Utils::o2a($scenario);
            $info_scenario[Common::HUMAN_NAME] = $scenario->getHumanName();
            $result[] = $info_scenario;
        }
        $this->ajax->success($result);
    }

    /**
     * @throws CoreException
     * @throws \ReflectionException
     */
    public function saveAll()
    {
        $scenarios = json_decode(Utils::init(AjaxParams::SCENARIOS), true);
        if (is_array($scenarios)) {
            foreach ($scenarios as $scenario_ajax) {
                $scenario = ScenarioManager::byId($scenario_ajax[AjaxParams::ID]);
                if (!is_object($scenario)) {
                    continue;
                }
                Utils::a2o($scenario, $scenario_ajax);
                $scenario->save();
            }
        }
        $this->ajax->success();
    }

    /**
     * @throws CoreException
     */
    public function autoCompleteGroup()
    {
        AuthentificationHelper::isConnectedAsAdminOrFail();
        $result = [];
        foreach (ScenarioManager::listGroup(Utils::init('term')) as $group) {
            $result[] = $group[Common::GROUP];
        }
        $this->ajax->success($result);
    }

    /**
     * @throws CoreException
     */
    public function toHtml()
    {
        $target = Utils::init(AjaxParams::ID);
        if ($target == Common::ALL || Utils::isJson($target)) {
            if (Utils::isJson($target)) {
                $scenario_ajax = json_decode($target, true);
                $scenarios = [];
                foreach ($scenario_ajax as $id) {
                    $scenarios[] = ScenarioManager::byId($id);
                }
            } else {
                $scenarios = ScenarioManager::all();
            }
            $result = [];
            foreach ($scenarios as $scenario) {
                $result[] = $scenario->toHtml(Utils::init(AjaxParams::VERSION));
            }
            $this->ajax->success($result);
        } else {
            $scenario = ScenarioManager::byId($target);
            if (is_object($scenario)) {
                $this->ajax->success($scenario->toHtml(Utils::init(AjaxParams::VERSION)));
            }
        }
        $this->ajax->success();
    }

    /**
     * @throws CoreException
     */
    public function remove()
    {
        AuthentificationHelper::isConnectedAsAdminOrFail();
        $scenario = ScenarioManager::byId(Utils::initInt(AjaxParams::ID));
        if (!is_object($scenario)) {
            throw new CoreException(__('Scénario ID inconnu'));
        }
        if (!$scenario->hasRight('w')) {
            throw new CoreException(__('Vous n\'êtes pas autorisé à faire cette action'));
        }
        $scenario->remove();
        $this->ajax->success();
    }

    /**
     * @throws CoreException
     */
    public function emptyLog()
    {
        AuthentificationHelper::isConnectedAsAdminOrFail();
        $scenario = ScenarioManager::byId(Utils::initInt(AjaxParams::ID));
        if (!is_object($scenario)) {
            throw new CoreException(__('Scénario ID inconnu'));
        }
        if (!$scenario->hasRight('w')) {
            throw new CoreException(__('Vous n\'êtes pas autorisé à faire cette action'));
        }
        if (file_exists(NEXTDOM_LOG . '/scenarioLog/scenario' . $scenario->getId() . '.log')) {
            unlink(NEXTDOM_LOG . '/scenarioLog/scenario' . $scenario->getId() . '.log');
        }
        $this->ajax->success();
    }

    /**
     * @throws CoreException
     * @throws \ReflectionException
     */
    public function copy()
    {
        AuthentificationHelper::isConnectedAsAdminOrFail();
        $scenario = ScenarioManager::byId(Utils::initInt(AjaxParams::ID));
        if (!is_object($scenario)) {
            throw new CoreException(__('Scénario ID inconnu'));
        }
        $this->ajax->success(Utils::o2a($scenario->copy(Utils::init(Common::NAME))));
    }

    /**
     * @throws CoreException
     * @throws \ReflectionException
     */
    public function get()
    {
        $scenario = ScenarioManager::byId(Utils::initInt(AjaxParams::ID));
        if (!is_object($scenario)) {
            throw new CoreException(__('Scénario ID inconnu'));
        }
        $result = Utils::o2a($scenario);
        $result[Common::TRIGGER] = NextDomHelper::toHumanReadable($result[Common::TRIGGER]);
        $result['forecast'] = $scenario->calculateScheduleDate();
        $result['elements'] = [];
        foreach ($scenario->getElement() as $element) {
            $result['elements'][] = $element->getAjaxElement();
        }
        $result['scenarioLinkBy'] = [NextDomObj::SCENARIO => []];
    		$scenarioUsedBy = $scenario->getUsedBy();
    		foreach ($scenarioUsedBy[NextDomObj::SCENARIO] as $scenarioLink) {
      			if($scenarioLink->getId() == $scenario->getId()){
      				  continue;
      			}
    			  $result['scenarioLinkBy'][NextDomObj::SCENARIO][$scenarioLink->getId()] = [AjaxParams::ID => $scenarioLink->getId(),Common::NAME => $scenarioLink->getHumanName(),'isActive' => $scenarioLink->getIsActive(),'isVisible' => $scenarioLink->getIsVisible()];
    		}
        $result['scenarioLinkIn'] = [NextDomObj::SCENARIO => []];
    		$scenarioUse = $scenario->getUse();
    		foreach ($scenarioUse[NextDomObj::SCENARIO] as $scenarioLink) {
      			if($scenarioLink->getId() == $scenario->getId()){
      				  continue;
      			}
      			$result['scenarioLinkIn'][NextDomObj::SCENARIO][$scenarioLink->getId()] = [AjaxParams::ID => $scenarioLink->getId(),Common::NAME => $scenarioLink->getHumanName(),'isActive' => $scenarioLink->getIsActive(),'isVisible' => $scenarioLink->getIsVisible()];
    		}
        $this->ajax->success($result);
    }

    /**
     * Save scenario
     *
     * @throws CoreException
     * @throws \ReflectionException
     */
    public function save()
    {
        AuthentificationHelper::isConnectedAsAdminOrFail();
        if (!Utils::isJson(Utils::init(AjaxParams::SCENARIO))) {
            throw new CoreException(__('Champs json invalide'));
        }
        // Check if scenario has time dependency
        $timeDependency = 0;
        foreach (['#time#', '#seconde#', '#heure#', '#minute#', '#jour#', '#mois#', '#annee#', '#timestamp#', '#date#', '#semaine#', '#sjour#', '#njour#', '#smois#'] as $keyword) {
            if (strpos(Utils::init(AjaxParams::SCENARIO), $keyword) !== false) {
                $timeDependency = 1;
                break;
            }
        }

        // Check if scenario must return a value
        // Loop for futur cases ?
        $hasReturn = 0;
        foreach (['scenario_return'] as $keyword) {
            if (strpos(Utils::init(AjaxParams::SCENARIO), $keyword) !== false) {
                $hasReturn = 1;
                break;
            }
        }

        // Prepare object from Ajax data
        $scenarioAjaxData = json_decode(Utils::init(AjaxParams::SCENARIO), true);
        if (isset($scenarioAjaxData[AjaxParams::ID])) {
            $targetScenario = ScenarioManager::byId($scenarioAjaxData[AjaxParams::ID]);
        }
        if (!isset($targetScenario) || !is_object($targetScenario)) {
            $targetScenario = new Scenario();
        } elseif (!$targetScenario->hasRight('w')) {
            throw new CoreException(__('Vous n\'êtes pas autorisé à faire cette action'));
        }
        if (!isset($scenarioAjaxData[Common::TRIGGER])) {
            $targetScenario->setTrigger([]);
        }
        if (!isset($scenarioAjaxData['schedule'])) {
            $targetScenario->setSchedule([]);
        }
        Utils::a2o($targetScenario, $scenarioAjaxData);
        $targetScenario->setConfiguration('timeDependency', $timeDependency);
        $targetScenario->setConfiguration('has_return', $hasReturn);

        // Save scenario elements
        $scenarioElementList = [];
        if (isset($scenarioAjaxData['elements'])) {
            foreach ($scenarioAjaxData['elements'] as $elementData) {
                $scenarioElementList[] = ScenarioElementManager::saveAjaxElement($elementData);
            }
            $targetScenario->setScenarioElement($scenarioElementList);
        }

        $targetScenario->save();
        $this->ajax->success(Utils::o2a($targetScenario));
    }

    /**
     * @throws \Exception
     */
    public function actionToHtml()
    {
        $result = null;
        if (Utils::init(AjaxParams::PARAMS) != '' && Utils::isJson(Utils::init(AjaxParams::PARAMS))) {
            $result = [];
            $params = json_decode(Utils::init(AjaxParams::PARAMS), true);
            foreach ($params as $param) {
                if (!isset($param['options'])) {
                    $param['options'] = [];
                }
                $html = ScenarioExpressionManager::getExpressionOptions($param['expression'], $param['options']);
                if (!isset($html['html']) || $html['html'] == '') {
                    continue;
                }
                $result[] = [
                    'html' => $html,
                    AjaxParams::ID => $param[AjaxParams::ID],
                ];
            }
        }
        if ($result !== null) {
            $this->ajax->success($result);
        } else {
            $this->ajax->success(ScenarioExpressionManager::getExpressionOptions(Utils::init(AjaxParams::EXPRESSION), Utils::init(AjaxParams::OPTION)));
        }
    }

    /**
     * @throws CoreException
     */
    public function templateupload()
    {
        $uploadDir = FoldersAndFilesReferential::SCENARIO_TEMPLATE_FORLDER;
        Utils::readUploadedFile($_FILES, "file", $uploadDir, 10, [".json"]);
        $this->ajax->success();
    }
}