YetiForceCompany/YetiForceCRM

View on GitHub
modules/Settings/Workflows/models/Module.php

Summary

Maintainability
B
6 hrs
Test Coverage
F
3%
<?php
/* +***********************************************************************************
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
 * ("License"); You may not use this file except in compliance with the License
 * The Original Code is:  vtiger CRM Open Source
 * The Initial Developer of the Original Code is vtiger.
 * Portions created by vtiger are Copyright (C) vtiger.
 * All Rights Reserved.
 * Contributor(s): YetiForce S.A.
 * *********************************************************************************** */

require_once 'modules/com_vtiger_workflow/include.php';
require_once 'modules/com_vtiger_workflow/expression_engine/VTExpressionsManager.php';

/**
 * Class settings workflows module model.
 */
class Settings_Workflows_Module_Model extends Settings_Vtiger_Module_Model
{
    /**
     * Base table name.
     *
     * @var string
     */
    public $baseTable = 'com_vtiger_workflows';

    /**
     * Base table index column name.
     *
     * @var string
     */
    public $baseIndex = 'workflow_id';

    /**
     * Fields visible on list view array.
     *
     * @var array
     */
    public $listFields = ['summary' => 'Summary', 'module_name' => 'Module', 'execution_condition' => 'Execution Condition', 'all_tasks' => 'LBL_ALL_TASKS', 'active_tasks' => 'LBL_ACTIVE_TASKS'];

    /**
     * All fields list.
     *
     * @var array
     */
    public static $allFields = [
        'module_name',
        'summary',
        'conditions',
        'execution_condition',
        'filtersavedinnew',
        'defaultworkflow',
        'type',
        'schtypeid',
        'schdayofmonth',
        'schdayofweek',
        'schannualdates',
        'schtime',
        'nexttrigger_time',
    ];

    /**
     * Module name.
     *
     * @var string
     */
    public $name = 'Workflows';

    /**
     * Workflow triggers list.
     *
     * @var array
     */
    public static $triggerTypes = [
        1 => 'ON_FIRST_SAVE',
        4 => 'ON_MODIFY',
        3 => 'ON_EVERY_SAVE',
        2 => 'ONCE',
        5 => 'ON_DELETE',
        6 => 'ON_SCHEDULE',
        7 => 'MANUAL',
        8 => 'TRIGGER',
        9 => 'BLOCK_EDIT',
        //10 => 'ON_RELATED',
    ];

    /**
     * Function to get the url for default view of the module.
     *
     * @return string - url
     */
    public static function getDefaultUrl()
    {
        return 'index.php?module=Workflows&parent=Settings&view=List';
    }

    /**
     * Function to get the url for create view of the module.
     *
     * @return string - url
     */
    public static function getCreateViewUrl()
    {
        return "javascript:Settings_Workflows_List_Js.triggerCreate('index.php?module=Workflows&parent=Settings&view=Edit')";
    }

    /**
     * Get create new record url.
     *
     * @return string
     */
    public static function getCreateRecordUrl()
    {
        return 'index.php?module=Workflows&parent=Settings&view=Edit';
    }

    /**
     * Returns url for import view.
     *
     * @return string url
     */
    public static function getImportViewUrl()
    {
        return 'index.php?module=Workflows&parent=Settings&view=Import';
    }

    /**
     * Get supported modules list.
     *
     * @return array
     */
    public static function getSupportedModules()
    {
        $moduleModels = Vtiger_Module_Model::getAll([0, 2]);
        $supportedModuleModels = [];
        foreach ($moduleModels as $tabId => $moduleModel) {
            if ($moduleModel->isWorkflowSupported()) {
                $supportedModuleModels[$tabId] = $moduleModel;
            }
        }
        return $supportedModuleModels;
    }

    /**
     * Get supported triggers list.
     *
     * @return array
     */
    public static function getTriggerTypes()
    {
        return self::$triggerTypes;
    }

    /**
     * Get expressions list.
     *
     * @return array
     */
    public static function getExpressions()
    {
        $mem = new VTExpressionsManager();

        return $mem->expressionFunctions();
    }

    /** {@inheritdoc} */
    public function getListFields(): array
    {
        if (!property_exists($this, 'listFieldModels')) {
            $fields = $this->listFields;
            $fieldObjects = [];
            $fieldsNoSort = ['module_name', 'execution_condition', 'all_tasks', 'active_tasks'];
            foreach ($fields as $fieldName => $fieldLabel) {
                if (\in_array($fieldName, $fieldsNoSort)) {
                    $fieldObjects[$fieldName] = new \App\Base(['name' => $fieldName, 'label' => $fieldLabel, 'sort' => false]);
                } else {
                    $fieldObjects[$fieldName] = new \App\Base(['name' => $fieldName, 'label' => $fieldLabel]);
                }
            }
            $this->listFieldModels = $fieldObjects;
        }
        return $this->listFieldModels;
    }

    /**
     * Delete all worklflows associated with module.
     *
     * @param vtlib\ModuleBasic $moduleInstance
     */
    public static function deleteForModule(vtlib\ModuleBasic $moduleInstance)
    {
        \App\Db::getInstance()->createCommand()->delete('com_vtiger_workflows', ['module_name' => $moduleInstance->name])->execute();
    }

    /**
     * Imports workflow template xml file.
     *
     * @param array $data
     *
     * @return int workflow id
     */
    public function importWorkflow(array $data)
    {
        $db = App\Db::getInstance();
        $dbCommand = App\Db::getInstance()->createCommand();
        $dbCommand->insert($this->getBaseTable(), $data['fields'])->execute();
        $workflowId = $db->getLastInsertID('com_vtiger_workflows_workflow_id_seq');
        $messages = ['id' => $workflowId];
        if (!empty($data['workflow_methods'])) {
            foreach ($data['workflow_methods'] as $method) {
                $this->importTaskMethod($method, $messages);
            }
        }
        if ($data['workflow_tasks']) {
            foreach ($data['workflow_tasks'] as $task) {
                include_once 'modules/com_vtiger_workflow/tasks/VTEntityMethodTask.php';
                include_once 'modules/com_vtiger_workflow/tasks/VTEmailTemplateTask.php';
                $taskManager = new VTTaskManager();
                $taskObject = $taskManager->unserializeTask(base64_decode($task['task']));
                if (!empty($taskObject)) {
                    $dbCommand->insert('com_vtiger_workflowtasks', ['workflow_id' => $workflowId, 'summary' => $task['summary']])->execute();
                    $taskId = $db->getLastInsertID('com_vtiger_workflowtasks_task_id_seq');
                    $taskObject->workflowId = (int) $workflowId;
                    $taskObject->id = (int) $taskId;
                    $dbCommand->update('com_vtiger_workflowtasks', ['task' => serialize($taskObject)], ['task_id' => $taskId])->execute();
                }
            }
        }
        return $messages;
    }

    /**
     * Returns infor for exporting of task method.
     *
     * @param int $methodName name of method
     *
     * @return array task method data
     */
    public static function exportTaskMethod($methodName)
    {
        $method = (new \App\Db\Query())->select(['workflowtasks_entitymethod_id', 'module_name', 'method_name', 'function_path', 'function_name'])->from('com_vtiger_workflowtasks_entitymethod')->where(['method_name' => $methodName])->one();
        $method['script_content'] = base64_encode(file_get_contents($method['function_path']));

        return $method;
    }

    /**
     * Function that creates task method.
     *
     * @param array $method   array containing method data
     * @param array $messages array containing returned error messages
     */
    public function importTaskMethod(array &$method, array &$messages)
    {
        $scriptData = base64_decode($method['script_content']);
        $functionPath = $method['function_path'];
        if (!$this->checkPathForImportMethod($functionPath)) {
            throw new \App\Exceptions\Security('ERR_NOT_ALLOWED_VALUE||function_path', 406);
        }
        if (!\preg_match('/^<\\?php/', $scriptData)) {
            throw new \App\Exceptions\Security('ERR_NOT_ALLOWED_VALUE||script_content', 406);
        }
        if (!file_exists($functionPath)) {
            $workflowsExists = file_exists(\dirname($functionPath));
            if ($workflowsExists && is_file(\dirname($functionPath))) {
                throw new \App\Exceptions\Security('ERR_DIRECTORY_CANNOT_BE_CREATED||function_path', 406);
            }
            if (!$workflowsExists) {
                mkdir(\dirname($functionPath));
            }
            if (false === file_put_contents($functionPath, $scriptData)) {
                throw new \App\Exceptions\IllegalValue('ERR_FAILED_TO_SAVE_SCRIPT||function_path', 406);
            }
        } else {
            require_once $functionPath;
            if (!method_exists($method['function_name'], $method['method_name'])) {
                throw new \App\Exceptions\IllegalValue('ERR_SCRIPT_EXISTS_FUNCTION_NOT||function_path', 406);
            }
        }
        $num = (new \App\Db\Query())
            ->from('com_vtiger_workflowtasks_entitymethod')
            ->where([
                'module_name' => $method['module_name'],
                'method_name' => $method['method_name'],
                'function_path' => $functionPath,
                'function_name' => $method['function_name'],
            ])->exists();
        if (!$num) {
            require_once 'modules/com_vtiger_workflow/VTEntityMethodManager.php';
            $emm = new VTEntityMethodManager();
            $emm->addEntityMethod($method['module_name'], $method['method_name'], $functionPath, $method['function_name']);
        }
    }

    /**
     * Check the path for importing the method.
     *
     * @param string $path
     *
     * @return bool Returns true if success
     */
    public function checkPathForImportMethod(string $path): bool
    {
        if ($returnVal = \preg_match('/^modules[\\\\|\\/]([A-Z][a-z,A-Z]+)[\\\\|\\/]workflows[\\\\|\\/][A-Z][a-z,A-Z]+\\.php$/', $path, $match)) {
            //Check if the module exists
            $returnVal = false !== \vtlib\Module::getInstance($match[1]);
        }
        return $returnVal;
    }

    /**
     * Update actions sequence.
     *
     * @param int    $wfIdToMove
     * @param int    $workflowBeforeId
     * @param string $moduleName
     *
     * @return void
     */
    public static function updateActionsSequence(int $wfIdToMove, int $workflowBeforeId, string $moduleName): void
    {
        if ($workflowBeforeId !== $wfIdToMove) {
            $db = \App\Db::getInstance();
            $caseSequence = 'CASE';
            $sequence = 0;

            $moduleWorkflows = array_keys(self::getWorkflowActionsForModule($moduleName));
            foreach ($moduleWorkflows as $wfId) {
                if ($wfIdToMove === $wfId) {
                    continue;
                }
                if ($wfId === $workflowBeforeId) {
                    $caseSequence .= " WHEN workflow_id = {$db->quoteValue($wfIdToMove)} THEN {$db->quoteValue($sequence)}";
                    ++$sequence;
                }
                $caseSequence .= " WHEN workflow_id = {$db->quoteValue($wfId)} THEN {$db->quoteValue($sequence)}";
                ++$sequence;
            }
            $caseSequence .= ' END';

            $db->createCommand()->update('com_vtiger_workflows', [
                'sequence' => new yii\db\Expression($caseSequence),
            ], ['workflow_id' => $moduleWorkflows])->execute();
        }
    }

    /**
     * Update tasks sequence.
     *
     * @param array $tasks
     *
     * @return void
     */
    public static function updateTasksSequence(array $tasks): void
    {
        $createCommand = \App\Db::getInstance()->createCommand();
        foreach ($tasks as $sequence => $id) {
            $createCommand->update('com_vtiger_workflowtasks', ['sequence' => $sequence], ['task_id' => $id])->execute();
        }
    }

    /**
     * Get workflow actions for module.
     *
     * @param string $moduleName
     *
     * @return array
     */
    public static function getWorkflowActionsForModule(string $moduleName): array
    {
        return (new \App\Db\Query())->select(['workflow_id', 'summary'])
            ->from('com_vtiger_workflows')
            ->where(['module_name' => $moduleName])
            ->orderBy(['sequence' => SORT_ASC])
            ->createCommand()->queryAllByGroup(1);
    }
}