<?php
namespace XF;
use function array_key_exists;
class PermissionCache
{
protected $db;
protected $globalPerms = [];
protected $contentPerms = [];
protected $globalCacheRun = [];
public function __construct(Db\AbstractAdapter $db)
{
$this->db = $db;
}
public function getPermissionSet($permissionCombinationId)
{
return new PermissionSet($this, $permissionCombinationId);
}
public function getGlobalPerms($permissionCombinationId)
{
// value will be null if we failed to retrieve the permissions
if (array_key_exists($permissionCombinationId, $this->globalPerms))
{
return $this->globalPerms[$permissionCombinationId];
}
$cache = $this->db->fetchOne("
SELECT cache_value
FROM xf_permission_combination
WHERE permission_combination_id = ?
", $permissionCombinationId);
if ($cache)
{
$cache = $this->decodePermissionCache($cache);
}
if (!$cache)
{
$cache = null;
}
$this->globalPerms[$permissionCombinationId] = $cache;
return $cache;
}
public function setGlobalPerms($permissionCombinationId, array $perms)
{
$this->globalPerms[$permissionCombinationId] = $perms;
}
public function getContentPerms($permissionCombinationId, $contentType, $contentId)
{
if (
isset($this->contentPerms[$permissionCombinationId][$contentType])
&& array_key_exists($contentId, $this->contentPerms[$permissionCombinationId][$contentType])
)
{
return $this->contentPerms[$permissionCombinationId][$contentType][$contentId];
}
if (isset($this->globalCacheRun[$contentType][$permissionCombinationId]))
{
// cacheAllContentPerms was called, but there were no results in the cache
// this would imply we're attempting to look up permissions for a non-existent content ID
// in this case, just bail out early
return null;
}
$cache = $this->db->fetchOne("
SELECT cache_value
FROM xf_permission_cache_content
WHERE permission_combination_id = ?
AND content_type = ?
AND content_id = ?
", [$permissionCombinationId, $contentType, $contentId]);
if ($cache)
{
$cache = $this->decodePermissionCache($cache);
}
if (!$cache)
{
$cache = null;
}
$this->contentPerms[$permissionCombinationId][$contentType][$contentId] = $cache;
return $cache;
}
public function cacheAllContentPerms($permissionCombinationId, $contentType)
{
if (isset($this->globalCacheRun[$contentType][$permissionCombinationId]))
{
return;
}
$this->globalCacheRun[$contentType][$permissionCombinationId] = true;
$permsResult = $this->db->fetchPairs("
SELECT content_id, cache_value
FROM xf_permission_cache_content
WHERE permission_combination_id = ?
AND content_type = ?
", [$permissionCombinationId, $contentType]);
foreach ($permsResult AS $contentId => $cache)
{
$cache = $this->decodePermissionCache($cache);
$this->contentPerms[$permissionCombinationId][$contentType][$contentId] = $cache;
}
}
public function cacheContentPermsByIds($permissionCombinationId, $contentType, array $contentIds)
{
if (!$contentIds)
{
return;
}
foreach ($contentIds AS $k => $contentId)
{
if (isset($this->contentPerms[$permissionCombinationId][$contentType][$contentId]))
{
unset($contentIds[$k]);
}
}
if (!$contentIds)
{
return;
}
$permsResult = $this->db->fetchPairs("
SELECT content_id, cache_value
FROM xf_permission_cache_content
WHERE permission_combination_id = ?
AND content_type = ?
AND content_id IN (" . $this->db->quote($contentIds) . ")
", [$permissionCombinationId, $contentType]);
foreach ($permsResult AS $contentId => $cache)
{
$cache = $this->decodePermissionCache($cache);
$this->contentPerms[$permissionCombinationId][$contentType][$contentId] = $cache;
}
}
public function cacheMultipleContentPermsForContent(array $permissionCombinationIds, $contentType, $contentId)
{
if (!$permissionCombinationIds)
{
return;
}
$permsResult = $this->db->fetchPairs("
SELECT permission_combination_id, cache_value
FROM xf_permission_cache_content
WHERE permission_combination_id IN (" . $this->db->quote($permissionCombinationIds) . ")
AND content_type = ?
AND content_id = ?
", [$contentType, $contentId]);
foreach ($permsResult AS $permissionCombinationId => $cache)
{
$cache = $this->decodePermissionCache($cache);
$this->contentPerms[$permissionCombinationId][$contentType][$contentId] = $cache;
}
}
protected function decodePermissionCache($cache)
{
$cacheDecoded = @json_decode($cache, true);
if ($cacheDecoded === null && \XF::options()->currentVersionId < 2010010)
{
$cacheDecoded = @unserialize($cache);
}
return $cacheDecoded ?: null;
}
public function setContentPerms($permissionCombinationId, $contentType, $contentId, array $perms)
{
$this->contentPerms[$permissionCombinationId][$contentType][$contentId] = $perms;
}
public function bulkSetContentPerms($permissionCombinationId, $contentType, array $permsPerContent)
{
foreach ($permsPerContent AS $contentId => $perms)
{
$this->contentPerms[$permissionCombinationId][$contentType][$contentId] = $perms;
}
}
}