YetiForceCompany/YetiForceCRM

View on GitHub
app/ModuleHierarchy.php

Summary

Maintainability
D
2 days
Test Coverage
F
28%
<?php

namespace App;

/**
 * Modules hierarchy basic class.
 *
 * @package App
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 * @author    Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
 */
class ModuleHierarchy
{
    protected static $hierarchy;
    protected static $modulesByLevels = [];

    public static function init()
    {
        if (isset(static::$hierarchy)) {
            return true;
        }
        static::$hierarchy = require ROOT_DIRECTORY . '/app_data/moduleHierarchy.php';
        foreach (static::$hierarchy['modulesHierarchy'] as $module => $details) {
            if (Module::isModuleActive($module) && Privilege::isPermitted($module)) {
                static::$modulesByLevels[$details['level']][$module] = $details;
            }
        }
    }

    public static function getModulesHierarchy()
    {
        return static::$hierarchy['modulesHierarchy'];
    }

    public static function getModuleLevel($moduleName)
    {
        return isset(static::$hierarchy['modulesHierarchy'][$moduleName]) ? static::$hierarchy['modulesHierarchy'][$moduleName]['level'] : false;
    }

    public static function getModulesMap1M($moduleName)
    {
        if (isset(static::$hierarchy['modulesMap1M'][$moduleName])) {
            return static::$hierarchy['modulesMap1M'][$moduleName];
        }
        return [];
    }

    public static function getModulesMapMMBase()
    {
        if (isset(static::$hierarchy['modulesMapMMBase'])) {
            return static::$hierarchy['modulesMapMMBase'];
        }
        return false;
    }

    public static function getModulesMapMMCustom($moduleName)
    {
        if (isset(static::$hierarchy['modulesMapMMCustom'][$moduleName])) {
            return static::$hierarchy['modulesMapMMCustom'][$moduleName];
        }
        return false;
    }

    public static function getModulesByLevel($level = null)
    {
        if (null === $level) {
            return static::$modulesByLevels;
        }
        if (isset(static::$modulesByLevels[$level])) {
            return static::$modulesByLevels[$level];
        }
        return [];
    }

    /**
     * Get modules list by uitype field.
     *
     * @param int $uitype
     *
     * @return array
     */
    public static function getModulesByUitype($uitype)
    {
        switch ($uitype) {
            case 67:
                $level = 0;
                break;
            case 66:
                $level = 1;
                break;
            case 68:
                $level = 2;
                break;
            case 64:
                $level = 3;
                break;
            case 65:
                $level = 4;
                break;
            default:
                break;
        }
        return static::getModulesByLevel($level);
    }

    public static function accessModulesByLevel($level = 0, $actionName = 'EditView')
    {
        $modules = [];
        if (isset(static::$modulesByLevels[$level])) {
            foreach (static::$modulesByLevels[$level] as $module => &$details) {
                if (Privilege::isPermitted($module, $actionName)) {
                    $modules[$module] = $details;
                }
            }
        }
        return $modules;
    }

    public static function accessModulesByParent($parent, $actionName = 'EditView')
    {
        $modules = [];
        foreach (static::$hierarchy['modulesHierarchy'] as $module => &$details) {
            if (Privilege::isPermitted($module, $actionName) && isset($details['parentModule'])) {
                $modules[$details['parentModule']][$module] = $details;
            }
        }
        return $modules[$parent];
    }

    public static function getMappingRelatedField($moduleName)
    {
        $return = false;
        switch ((string) static::getModuleLevel($moduleName)) {
            case '0':
                $return = 'link';
                break;
            case '1':
                $return = 'process';
                break;
            case '2':
                $return = 'subprocess';
                break;
            case '3':
                $return = 'subprocess_sl';
                break;
            case '4':
                $return = 'linkextend';
                break;
            default:
                break;
        }
        return $return;
    }

    /**
     * The function takes a hierarchy relationship.
     *
     * @param string $moduleName
     * @param bool   $field
     *
     * @return array
     */
    public static function getRelationFieldByHierarchy($moduleName, $field = false)
    {
        if (false !== $field && isset(static::$hierarchy['modulesMapRelatedFields'][$moduleName][$field])) {
            return static::$hierarchy['modulesMapRelatedFields'][$moduleName][$field];
        }
        if (isset(static::$hierarchy['modulesMapRelatedFields'][$moduleName])) {
            return static::$hierarchy['modulesMapRelatedFields'][$moduleName];
        }
        return [];
    }

    public static function getUitypeByModule($moduleName)
    {
        switch (static::getModuleLevel($moduleName)) {
            case 0:
                $return = 67;
                break;
            case 1:
                $return = 66;
                break;
            case 2:
                $return = 68;
                break;
            case 3:
                $return = 64;
                break;
            case 4:
                $return = 65;
                break;
            default:
                break;
        }
        return $return;
    }

    /**
     * Get child modules.
     *
     * @param string $moduleName
     * @param int[]  $hierarchy
     *
     * @return string[]
     */
    public static function getChildModules($moduleName, $hierarchy = [1])
    {
        $modules = [];
        switch (static::getModuleLevel($moduleName)) {
            case 0:
                $is1Level = \in_array(1, $hierarchy);
                $isLevel4 = \in_array(4, $hierarchy);
                if ($is1Level && $isLevel4) {
                    $modules = array_keys(array_merge(static::getModulesByLevel(1), static::getModulesByLevel(4)));
                } elseif ($is1Level) {
                    $modules = array_keys(static::getModulesByLevel(1));
                } elseif ($isLevel4) {
                    $modules = array_keys(static::getModulesByLevel(4));
                }
                break;
            case 1:
                if ($levelMod = static::getModulesByLevel(2)) {
                    foreach ($levelMod as $mod => $details) {
                        if ($moduleName === $details['parentModule']) {
                            $modules[] = $mod;
                        }
                    }
                }
                break;
            case 2:
                if (\in_array(3, $hierarchy)) {
                    $modules = array_keys(static::getModulesByLevel(3));
                }
                break;
            default:
                break;
        }
        return $modules;
    }

    /**
     * Get related records by hierarchy.
     *
     * @param int   $record
     * @param array $hierarchy
     *
     * @return int[]
     */
    public static function getRelatedRecords($record, $hierarchy)
    {
        $moduleName = Record::getType($record);
        $records = $recordsLevel1 = $recordsLevel2 = [];
        if (\in_array(0, $hierarchy)) {
            $records[] = $record;
        }
        $modules = static::getChildModules($moduleName, $hierarchy);
        if ($modules) {
            $fields = Field::getRelatedFieldForModule(false, $moduleName);
            foreach ($fields as $field) {
                if (\in_array($field['name'], $modules)) {
                    $recordsByField = static::getRelatedRecordsByField($record, $field);
                    $recordsLevel1 = array_merge($recordsLevel1, $recordsByField);
                }
            }
        }
        $level = static::getModuleLevel($moduleName);
        if (!(0 == $level && !\in_array(1, $hierarchy))) {
            $records = array_merge($records, $recordsLevel1);
        }
        if (0 === $level) {
            if (\in_array(2, $hierarchy)) {
                $modules = static::getChildModules($moduleName, [1]);
                if ($modules) {
                    $fields = Field::getRelatedFieldForModule(false, $moduleName);
                    foreach ($fields as $field) {
                        if (\in_array($field['name'], $modules)) {
                            $recordsByField = static::getRelatedRecordsByField($record, $field);
                            $recordsLevel2 = array_merge($recordsLevel2, $recordsByField);
                        }
                    }
                }
                foreach ($recordsLevel2 as $record) {
                    $recordsByHierarchy = static::getRelatedRecords($record, $hierarchy);
                    $records = array_merge($records, $recordsByHierarchy);
                }
            }
            if (\in_array(3, $hierarchy)) {
                $records = array_merge($records, $recordsLevel1);
            }
        }
        return array_unique($records);
    }

    /**
     * Get related records by field.
     *
     * @param int   $record
     * @param array $field
     *
     * @return int[]
     */
    protected static function getRelatedRecordsByField($record, $field)
    {
        $queryGenerator = new QueryGenerator($field['name']);
        $queryGenerator->setFields(['id']);
        $queryGenerator->addNativeCondition([$field['tablename'] . '.' . $field['columnname'] => $record]);

        return $queryGenerator->createQuery()->column();
    }

    /**
     * Function to get array of queries. Quries are used to create union.
     *
     * @param int      $record
     * @param string   $moduleName
     * @param array    $hierarchy
     * @param Db\Query $subQuery
     *
     * @return array
     */
    private static function getQueriesForRelatedRecords(int $record, string $moduleName, array $hierarchy, Db\Query $subQuery = null): array
    {
        $modules = static::getChildModules($moduleName, $hierarchy);
        $queries = [];
        if ($modules) {
            $fields = Field::getRelatedFieldForModule(false, $moduleName);
            foreach ($fields as $field) {
                if (\in_array($field['name'], $modules)) {
                    $queryGenerator = new QueryGenerator($field['name']);
                    $queryGenerator->setFields(['id']);
                    if ($subQuery) {
                        $queryGenerator->addNativeCondition([$field['tablename'] . '.' . $field['columnname'] => $subQuery]);
                    } else {
                        $queryGenerator->addNativeCondition([$field['tablename'] . '.' . $field['columnname'] => $record]);
                    }
                    $tempQuery = $queryGenerator->createQuery();
                    $queries[] = $tempQuery;
                    $queries = array_merge($queries, static::getQueriesForRelatedRecords($record, $field['name'], $hierarchy, clone $tempQuery));
                }
            }
        }
        return $queries;
    }

    /**
     * Get related query by hierarchy.
     *
     * @param int   $record
     * @param array $hierarchy
     *
     * @return Db\Query|null
     */
    public static function getQueryRelatedRecords(int $record, array $hierarchy): ?Db\Query
    {
        $moduleName = Record::getType($record);
        $queries = static::getQueriesForRelatedRecords($record, $moduleName, $hierarchy);
        if (0 === \count($queries)) {
            return null;
        }
        $subQuery = $queries[0];
        unset($queries[0]);
        foreach ($queries as $query) {
            $subQuery->union($query);
        }
        return $subQuery;
    }

    /**
     * Get fields for list filter.
     *
     * @param string $moduleName
     *
     * @return array
     */
    public static function getFieldsForListFilter(string $moduleName): array
    {
        $fields = [];
        $moduleId = \App\Module::getModuleId($moduleName);
        foreach (static::getHierarchyByRelation() as $relations) {
            foreach ($relations as $relation) {
                if ($relation['related_tabid'] === $moduleId && !empty($relation['rel_field_name'])) {
                    $fields[$relation['field_name']][\App\Module::getModuleName($relation['tabid'])] = [$relation['rel_field_name'] => \App\Module::getModuleName($relation['rel_tabid'])];
                }
            }
        }
        return $fields;
    }

    /**
     * Get hierarchy info by relation.
     *
     * @param int|null $relationId
     *
     * @return array
     */
    public static function getHierarchyByRelation(int $relationId = null): array
    {
        if (Cache::has('HierarchyByRelation', '')) {
            $data = Cache::get('HierarchyByRelation', '');
        } else {
            $data = [];
            $dataReader = (new \App\Db\Query())
                ->select(['SR.tabid', 'SR.field_name', 'SR.related_tabid', 'rel_field_name' => 'RR.field_name', 'rel_tabid' => 'RR.tabid', 'a_yf_record_list_filter.*'])
                ->from('a_yf_record_list_filter')
                ->leftJoin(['SR' => 'vtiger_relatedlists'], 'SR.relation_id=a_yf_record_list_filter.relationid')
                ->leftJoin(['RR' => 'vtiger_relatedlists'], 'RR.relation_id=a_yf_record_list_filter.rel_relationid')
                ->createCommand()->query();
            while ($row = $dataReader->read()) {
                $data[$row['relationid']][] = $row;
            }
            Cache::save('HierarchyByRelation', '', $data, Cache::LONG);
        }
        if (null === $relationId) {
            return $data;
        }

        return $data[$relationId] ?? [];
    }
}

ModuleHierarchy::init();