Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Service/UpdatePermissions.php
<?php

namespace XF\Service;

use function
count, intval, is_array;

class
UpdatePermissions extends AbstractService
{
   
/**
     * @var \XF\Entity\User|null
     */
   
protected $user = null;

   
/**
     * @var \XF\Entity\UserGroup|null
     */
   
protected $userGroup = null;

    protected
$contentType = '';
    protected
$contentId = 0;

    public function
setUser(\XF\Entity\User $user)
    {
        if (!
$user->exists())
        {
            throw new \
InvalidArgumentException("User must exist");
        }

       
$this->user = $user;
       
$this->userGroup = null;

        return
$this;
    }

    public function
getUser()
    {
        return
$this->user;
    }

    public function
setUserGroup(\XF\Entity\UserGroup $userGroup)
    {
       
$this->userGroup = $userGroup;
       
$this->user = null;

        return
$this;
    }

    public function
getUserGroup()
    {
        return
$this->userGroup;
    }

    public function
setContent($contentType, $contentId)
    {
       
$contentId = intval($contentId);
        if (!
$contentType || !$contentId)
        {
            throw new \
InvalidArgumentException("A content type and ID must be provided");
        }

       
$this->contentType = $contentType;
       
$this->contentId = $contentId;

        return
$this;
    }

    public function
getContent()
    {
        return [
$this->contentType, $this->contentId];
    }

    public function
setGlobal()
    {
       
$this->contentType = '';
       
$this->contentId = 0;

        return
$this;
    }

    public function
updatePermissions(array $values)
    {
       
$existingGrouped = $this->getExistingPermissionEntriesGrouped();
       
$permissionsGrouped = $this->getAvailablePermissionsGrouped();

       
$db = $this->db();
       
$db->beginTransaction();

        foreach (
$values AS $groupId => $groupValues)
        {
            if (!
is_array($groupValues))
            {
                continue;
            }

            foreach (
$groupValues AS $permissionId => $value)
            {
                if (!isset(
$permissionsGrouped[$groupId][$permissionId]))
                {
                    continue;
                }

               
$entry = $existingGrouped[$groupId][$permissionId] ?? null;
               
$permission = $permissionsGrouped[$groupId][$permissionId];

               
$this->writeEntry($permission, $value, $entry);
            }
        }

       
$db->commit();

        if (
$this->app->container()->isCached('permission.builder'))
        {
           
// permissions changing and we've already cached the data, so refresh
           
$this->app->permissionBuilder()->refreshData();
        }

       
$this->triggerCacheRebuild();
    }

    protected function
getExistingPermissionEntriesGrouped()
    {
        if (
$this->contentType)
        {
           
$finder = $this->finder('XF:PermissionEntryContent');
           
$finder->where([
               
'content_type' => $this->contentType,
               
'content_id' => $this->contentId
           
]);
        }
        else
        {
           
$finder = $this->finder('XF:PermissionEntry');
        }

       
$finder->where([
           
'user_id' => $this->user ? $this->user->user_id : 0,
           
'user_group_id' => $this->userGroup ? $this->userGroup->user_group_id : 0
       
]);

        return
$finder->fetch()->groupBy('permission_group_id', 'permission_id');
    }

    protected function
getAvailablePermissionsGrouped()
    {
       
/** @var \XF\Repository\Permission $permissionRepo */
       
$permissionRepo = $this->repository('XF:Permission');
        return
$permissionRepo->getPermissionsGrouped();
    }

    protected function
writeEntry(\XF\Entity\Permission $permission, $value, \XF\Mvc\Entity\Entity $entry = null)
    {
        if (
$value == 'unset' || $value === '0' || $value === 0)
        {
            if (
$entry)
            {
               
$entry->delete();
            }
            return
null;
        }

        if (!
$entry)
        {
            if (
$this->contentType)
            {
               
$entry = $this->em()->create('XF:PermissionEntryContent');
               
$entry->content_type = $this->contentType;
               
$entry->content_id = $this->contentId;
            }
            else
            {
               
$entry = $this->em()->create('XF:PermissionEntry');
            }

           
$entry->permission_group_id = $permission->permission_group_id;
           
$entry->permission_id = $permission->permission_id;
        }

       
$entry->user_id = $this->user ? $this->user->user_id : 0;
       
$entry->user_group_id = $this->userGroup ? $this->userGroup->user_group_id : 0;

        if (
$permission->permission_type == 'integer')
        {
           
$entry->permission_value = 'use_int';
           
$entry->permission_value_int = intval($value);
        }
        else
        {
           
$entry->permission_value = $value;
           
$entry->permission_value_int = 0;
        }

       
$entry->save();

        return
$entry;
    }

    public function
triggerCacheRebuild()
    {
       
/** @var \XF\Repository\PermissionCombination $combinationRepo */
       
$combinationRepo = $this->repository('XF:PermissionCombination');

        if (
$this->user)
        {
           
$combination = $combinationRepo->updatePermissionCombinationForUser($this->user, false);
           
$this->app->permissionBuilder()->rebuildCombination($combination);
        }
        else if (
$this->userGroup)
        {
           
$combinations = $combinationRepo->getPermissionCombinationsForUserGroup($this->userGroup->user_group_id);
            if (
count($combinations) > 10)
            {
               
$combinationIds = $combinations->keys();

               
// too much to build inline
               
$this->app->jobManager()->enqueueUnique(
                   
'permissionRebuild:' . substr(md5(implode(',', $combinationIds)), 0, 16),
                   
'XF:PermissionRebuildPartial',
                    [
'combinationIds' => $combinationIds]
                );
            }
            else
            {
               
$builder = $this->app->permissionBuilder();
                foreach (
$combinations AS $combination)
                {
                   
$builder->rebuildCombination($combination);
                }
            }
        }
        else
        {
           
// need to rebuild all combinations
           
$this->app->jobManager()->enqueueUnique('permissionRebuild', 'XF:PermissionRebuild');
        }
    }
}