YetiForceCompany/YetiForceCRM

View on GitHub
modules/Settings/Roles/models/Record.php

Summary

Maintainability
D
2 days
Test Coverage
D
60%
<?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.
 * *********************************************************************************** */

/**
 * Roles Record Model Class.
 */
class Settings_Roles_Record_Model extends Settings_Vtiger_Record_Model
{
    /**
     * Function to get the Id.
     *
     * @return <Number> Role Id
     */
    public function getId()
    {
        return $this->get('roleid');
    }

    /**
     * Function to get the Role Name.
     *
     * @return string
     */
    public function getName()
    {
        return $this->get('rolename');
    }

    /**
     * Function to get the depth of the role.
     *
     * @return <Number>
     */
    public function getDepth()
    {
        return $this->get('depth');
    }

    /**
     * Function to get Parent Role hierarchy as a string.
     *
     * @return string
     */
    public function getParentRoleString()
    {
        return $this->get('parentrole');
    }

    /**
     * Function to set the immediate parent role.
     *
     * @param mixed $parentRole
     *
     * @return <Settings_Roles_Record_Model> instance
     */
    public function setParent($parentRole)
    {
        $this->parent = $parentRole;

        return $this;
    }

    /**
     * Function to get the immediate parent role.
     *
     * @return <Settings_Roles_Record_Model> instance
     */
    public function getParent()
    {
        if (!isset($this->parent)) {
            $parentRoleString = $this->getParentRoleString();
            $parentComponents = explode('::', $parentRoleString);
            $noOfRoles = \count($parentComponents);
            if ($noOfRoles > 1) {
                $this->parent = self::getInstanceById($parentComponents[$noOfRoles - 2]);
            } else {
                $this->parent = null;
            }
        }
        return $this->parent;
    }

    /**
     * Function to get the immediate children roles.
     *
     * @return <Array> - List of Settings_Roles_Record_Model instances
     */
    public function getChildren()
    {
        if (!isset($this->children)) {
            $parentRoleString = $this->getParentRoleString();
            $currentRoleDepth = $this->getDepth();

            $dataReader = (new \App\Db\Query())->from('vtiger_role')
                ->where(['like', 'parentrole', $parentRoleString . '::%', false])
                ->andWhere(['depth' => $currentRoleDepth + 1])
                ->createCommand()->query();
            $roles = [];
            while ($row = $dataReader->read()) {
                $role = new self();
                $role->setData($row);
                $roles[$role->getId()] = $role;
            }
            $dataReader->close();
            $this->children = $roles;
        }
        return $this->children;
    }

    public function getSameLevelRoles()
    {
        if (!isset($this->children)) {
            $parentRoles = \App\PrivilegeUtil::getParentRole($this->getId());
            $currentRoleDepth = $this->getDepth();
            $parentRoleString = '';
            foreach ($parentRoles as $role) {
                if (empty($parentRoleString)) {
                    $parentRoleString = $role;
                } else {
                    $parentRoleString = $parentRoleString . '::' . $role;
                }
            }
            $dataReader = (new \App\Db\Query())->from('vtiger_role')
                ->where(['like', 'parentrole', $parentRoleString . '::%', false])
                ->andWhere(['depth' => $currentRoleDepth])
                ->createCommand()->query();

            $roles = [];
            while ($row = $dataReader->read()) {
                $role = new self();
                $role->setData($row);
                $roles[$role->getId()] = $role;
            }
            $dataReader->close();
            $this->children = $roles;
        }
        return $this->children;
    }

    /**
     * Function to get all the children roles.
     *
     * @return Settings_Roles_Record_Model[] List of Settings_Roles_Record_Model instances
     */
    public function getAllChildren()
    {
        $dataReader = (new App\Db\Query())->from('vtiger_role')
            ->where(['like', 'parentrole', $this->getParentRoleString() . '::%', false])
            ->createCommand()->query();
        $roles = [];
        while ($row = $dataReader->read()) {
            $role = new self();
            $role->setData($row);
            $roles[$role->getId()] = $role;
        }
        $dataReader->close();

        return $roles;
    }

    /**
     * Function returns profiles related to the current role.
     *
     * @return array - profile ids
     */
    public function getProfileIdList()
    {
        return (new App\Db\Query())->select(['profileid'])->from('vtiger_role2profile')->where(['roleid' => $this->getId()])->column();
    }

    /**
     * Function to get the profile id if profile is directly related to role.
     *
     * @return id
     */
    public function getDirectlyRelatedProfileId()
    {
        $roleId = $this->getId();
        if (empty($roleId)) {
            return false;
        }
        $row = (new App\Db\Query())->select(['directly_related_to_role', 'vtiger_profile.profileid'])
            ->from('vtiger_role2profile')
            ->innerJoin('vtiger_profile', 'vtiger_profile.profileid = vtiger_role2profile.profileid')
            ->where(['vtiger_role2profile.roleid' => $this->getId()])
            ->one();
        if ($row && 1 === (int) $row['directly_related_to_role']) {
            return $row['profileid'];
        }
        return false;
    }

    /**
     * Function to get the Edit View Url for the Role.
     *
     * @return string
     */
    public function getEditViewUrl()
    {
        return 'index.php?module=Roles&parent=Settings&view=Edit&record=' . $this->getId();
    }

    /**
     * Function to get the Create Child Role Url for the current role.
     *
     * @return string
     */
    public function getCreateChildUrl()
    {
        return '?module=Roles&parent=Settings&view=Edit&parent_roleid=' . $this->getId();
    }

    /**
     * Function to get the Delete Action Url for the current role.
     *
     * @return string
     */
    public function getDeleteActionUrl()
    {
        return '?module=Roles&parent=Settings&view=DeleteAjax&record=' . $this->getId();
    }

    /**
     * Function to get all the profiles associated with the current role.
     *
     * @return <Array> Settings_Profiles_Record_Model instances
     */
    public function getProfiles()
    {
        if (!isset($this->profiles)) {
            $this->profiles = Settings_Profiles_Record_Model::getAllByRole($this->getId());
        }
        return $this->profiles;
    }

    /**
     * Function to add a child role to the current role.
     *
     * @param <Settings_Roles_Record_Model> $role
     *
     * @return Settings_Roles_Record_Model instance
     */
    public function addChildRole($role)
    {
        $role->setParent($this);
        $role->save();

        return $role;
    }

    /**
     * Function to move the current role and all its children nodes to the new parent role.
     *
     * @param <Settings_Roles_Record_Model> $newParentRole
     */
    public function moveTo($newParentRole)
    {
        $currentDepth = $this->getDepth();
        $currentParentRoleString = $this->getParentRoleString();

        $newDepth = $newParentRole->getDepth() + 1;
        $newParentRoleString = $newParentRole->getParentRoleString() . '::' . $this->getId();

        $depthDifference = $newDepth - $currentDepth;
        $allChildren = $this->getAllChildren();

        $this->set('depth', $newDepth);
        $this->set('parentrole', $newParentRoleString);
        $this->set('allowassignedrecordsto', $this->get('allowassignedrecordsto'));
        $this->save();

        foreach ($allChildren as $roleModel) {
            $oldChildDepth = $roleModel->getDepth();
            $newChildDepth = $oldChildDepth + $depthDifference;

            $oldChildParentRoleString = $roleModel->getParentRoleString();
            $newChildParentRoleString = str_replace($currentParentRoleString, $newParentRoleString, $oldChildParentRoleString);

            $roleModel->set('depth', $newChildDepth);
            $roleModel->set('parentrole', $newChildParentRoleString);
            $roleModel->set('allowassignedrecordsto', $roleModel->get('allowassignedrecordsto'));
            $roleModel->save();
        }
    }

    /**
     * Function to save the role.
     */
    public function save()
    {
        $db = App\Db::getInstance();
        $roleId = $this->getId();
        $mode = 'edit';
        $rolePreviousData = [];

        if (empty($roleId)) {
            $mode = '';
            $roleIdNumber = $db->getUniqueId('vtiger_role');
            $roleId = 'H' . $roleIdNumber;
        }
        $parentRole = $this->getParent();
        if (null !== $parentRole) {
            $this->set('depth', $parentRole->getDepth() + 1);
            $this->set('parentrole', $parentRole->getParentRoleString() . '::' . $roleId);
        }
        $searchunpriv = $this->get('searchunpriv');
        if (\is_array($searchunpriv)) {
            $searchunpriv = implode(',', $searchunpriv);
        }
        $permissionsRelatedField = $this->get('permissionsrelatedfield');
        if (\is_array($permissionsRelatedField)) {
            $permissionsRelatedField = implode(',', $permissionsRelatedField);
        }
        $values = [
            'rolename' => $this->getName(),
            'parentrole' => $this->getParentRoleString(),
            'depth' => $this->getDepth(),
            'allowassignedrecordsto' => $this->get('allowassignedrecordsto'),
            'assignedmultiowner' => $this->get('assignedmultiowner'),
            'changeowner' => (int) $this->get('changeowner'),
            'searchunpriv' => $searchunpriv,
            'clendarallorecords' => $this->get('clendarallorecords'),
            'listrelatedrecord' => $this->get('listrelatedrecord'),
            'previewrelatedrecord' => $this->get('previewrelatedrecord'),
            'editrelatedrecord' => (int) $this->get('editrelatedrecord'),
            'permissionsrelatedfield' => $permissionsRelatedField,
            'globalsearchadv' => (int) $this->get('globalsearchadv'),
            'auto_assign' => (int) $this->get('auto_assign'),
            'company' => (int) $this->get('company'),
        ];
        if ('edit' === $mode) {
            $rolePreviousData = App\PrivilegeUtil::getRoleDetail($roleId);
            $db->createCommand()->update('vtiger_role', $values, ['roleid' => $roleId])
                ->execute();
        } else {
            $values['roleid'] = $roleId;
            $db->createCommand()->insert('vtiger_role', $values)->execute();
            $insertedData = (new App\Db\Query())
                ->select([new \yii\db\Expression($db->quoteValue($roleId)), 'picklistvalueid', 'picklistid', 'sortid'])
                ->from('vtiger_role2picklist')
                ->where(['roleid' => $parentRole->getId()])
                ->all();

            $db->createCommand()->batchInsert('vtiger_role2picklist', ['roleid', 'picklistvalueid', 'picklistid', 'sortid'], $insertedData)->execute();
            $this->set('roleid', $roleId);
        }
        $profileIds = $this->get('profileIds');
        if ($rolePreviousData) {
            $oldProfileIds = $this->getProfileIdList();
            if ($rolePreviousData['listrelatedrecord'] != $this->get('listrelatedrecord')
                    || $rolePreviousData['previewrelatedrecord'] != $this->get('previewrelatedrecord')
                    || $rolePreviousData['editrelatedrecord'] != $this->get('editrelatedrecord')
                    || $rolePreviousData['permissionsrelatedfield'] != $permissionsRelatedField
                    || $rolePreviousData['searchunpriv'] != $searchunpriv
                || ($profileIds && !empty(array_merge(array_diff($profileIds, $oldProfileIds), array_diff($oldProfileIds, $profileIds))))) {
                \App\Privilege::setAllUpdater();
            }
        }
        if (empty($profileIds)) {
            $profiles = $this->getProfiles();
            if (!empty($profiles) && \count($profiles) > 0) {
                $profileIds = array_keys($profiles);
            }
        }
        if (!empty($profileIds)) {
            $noOfProfiles = \count($profileIds);
            if ($noOfProfiles > 0) {
                $db->createCommand()->delete('vtiger_role2profile', ['roleid' => $roleId])->execute();
                for ($i = 0; $i < $noOfProfiles; ++$i) {
                    $db->createCommand()->insert('vtiger_role2profile', ['roleid' => $roleId, 'profileid' => $profileIds[$i]])
                        ->execute();
                }
            }
        }

        \App\Cache::delete(__CLASS__, $roleId);
        \App\Cache::delete('RoleDetail', $roleId);
        \App\Cache::delete('getUsersByCompany', '');
        if ($this->get('company')) {
            \App\Cache::delete('getUsersByCompany', $this->get('company'));
        }
        \App\Cache::delete('getCompanyRoles', '');
        if (isset($rolePreviousData['company'])) {
            \App\Cache::delete('getUsersByCompany', $rolePreviousData['company']);
        }
    }

    /**
     * Function to delete the role.
     *
     * @param <Settings_Roles_Record_Model> $transferToRole
     */
    public function delete($transferToRole)
    {
        $db = App\Db::getInstance();
        $roleId = $this->getId();
        $transferRoleId = $transferToRole->getId();
        $usersInRole = $this->getUsersIds();
        $db->createCommand()->update('vtiger_user2role', ['roleid' => $transferRoleId], ['roleid' => $roleId])->execute();
        $db->createCommand()->delete('vtiger_role2profile', ['roleid' => $roleId])->execute();
        $db->createCommand()->delete('vtiger_group2role', ['roleid' => $roleId])->execute();
        $db->createCommand()->delete('vtiger_group2rs', ['roleandsubid' => $roleId])->execute();
        //delete handling for sharing rules
        \App\PrivilegeUtil::deleteRelatedSharingRules($roleId, 'Roles');
        $db->createCommand()->delete('vtiger_role', ['roleid' => $roleId])->execute();
        $allChildren = $this->getAllChildren();
        $transferParentRoleSequence = $transferToRole->getParentRoleString();
        $currentParentRoleSequence = $this->getParentRoleString();
        foreach ($allChildren as $roleId => $roleModel) {
            $oldChildParentRoleString = $roleModel->getParentRoleString();
            $newChildParentRoleString = str_replace($currentParentRoleSequence, $transferParentRoleSequence, $oldChildParentRoleString);
            $newChildDepth = \count(explode('::', $newChildParentRoleString)) - 1;
            $roleModel->set('depth', $newChildDepth);
            $roleModel->set('parentrole', $newChildParentRoleString);
            $roleModel->save();
        }
        \App\Privilege::setAllUpdater();
        if (\is_array($usersInRole)) {
            foreach ($usersInRole as $userid) {
                \App\UserPrivilegesFile::createUserPrivilegesfile($userid);
                \App\UserPrivilegesFile::createUserSharingPrivilegesfile($userid);
            }
        }
    }

    /** {@inheritdoc} */
    public function getRecordLinks(): array
    {
        $links = [];
        if ($this->getParent()) {
            $recordLinks = [
                [
                    'linktype' => 'LISTVIEWRECORD',
                    'linklabel' => 'LBL_EDIT_RECORD',
                    'linkurl' => $this->getEditViewUrl(),
                    'linkicon' => 'yfi yfi-full-editing-view',
                ],
                [
                    'linktype' => 'LISTVIEWRECORD',
                    'linklabel' => 'LBL_DELETE_RECORD',
                    'linkurl' => $this->getDeleteActionUrl(),
                    'linkicon' => 'fas fa-trash-alt',
                ],
            ];
            foreach ($recordLinks as $recordLink) {
                $links[] = Vtiger_Link_Model::getInstanceFromValues($recordLink);
            }
        }
        return $links;
    }

    /**
     * Function to get all the roles.
     *
     * @param bool $baseRole
     *
     * @return <Array> list of Role models <Settings_Roles_Record_Model>
     */
    public static function getAll($baseRole = false)
    {
        $query = (new App\Db\Query())->from('vtiger_role');
        if (!$baseRole) {
            $query->where(['<>', 'depth', 0]);
        }
        $dataReader = $query->orderBy(['parentrole' => SORT_DESC])
            ->createCommand()->query();
        $roles = [];
        while ($row = $dataReader->read()) {
            $role = new self();
            $role->setData($row);
            $roles[$role->getId()] = $role;
        }
        $dataReader->close();

        return $roles;
    }

    /**
     * Function to get the instance of Role model, given role id.
     *
     * @param int $roleId
     *
     * @return self|null
     */
    public static function getInstanceById($roleId)
    {
        if (!\App\Cache::staticHas(__CLASS__, $roleId)) {
            $instance = null;
            $row = \App\PrivilegeUtil::getRoleDetail($roleId);
            if ($row) {
                $instance = (new self())->setData($row);
            }
            \App\Cache::staticSave(__CLASS__, $roleId, $instance);
        }
        return \App\Cache::staticGet(__CLASS__, $roleId);
    }

    /**
     * Function to get the instance of Base Role model.
     *
     * @return Settings_Roles_Record_Model instance, if exists. Null otherwise
     */
    public static function getBaseRole()
    {
        $row = (new App\Db\Query())->from('vtiger_role')->where(['depth' => 0])->one();
        if ($row) {
            $instance = new self();
            $instance->setData($row);

            return $instance;
        }
        return null;
    }

    /** Function to get the instance of the role by Name.
     * @param type  $name             -- name of the role
     * @param mixed $excludedRecordId
     *
     * @return null/role instance
     */
    public static function getInstanceByName($name, $excludedRecordId = [])
    {
        $query = (new App\Db\Query())->from('vtiger_role')->where(['rolename' => $name]);
        if (!empty($excludedRecordId)) {
            $query->andWhere(['NOT IN', 'roleid', $excludedRecordId]);
        }
        $row = $query->one();
        if ($row) {
            $instance = new self();
            $instance->setData($row);

            return $instance;
        }
        return null;
    }

    /**
     * Function to get ids users in this role.
     *
     * @return int[]
     */
    public function getUsersIds()
    {
        return (new App\Db\Query())->select(['userid'])
            ->from('vtiger_user2role')
            ->where(['roleid' => $this->getId()])
            ->column();
    }

    /**
     * Function to get Users who are from this role.
     *
     * @return Users_Record_Model[] User record models list Users_Record_Model
     */
    public function getUsers()
    {
        $userIds = $this->getUsersIds();
        $usersList = [];
        foreach ($userIds as $userId) {
            $usersList[$userId] = Users_Record_Model::getInstanceById($userId, 'Users');
        }
        return $usersList;
    }

    /**
     * Get multi company.
     *
     * @return array
     */
    public function getMultiCompany()
    {
        return (new App\Db\Query())->select(['multicompanyid', 'company_name'])
            ->from('u_#__multicompany')
            ->where(['mulcomp_status' => 'PLL_ACTIVE'])
            ->all();
    }
}