Initial Upload
This commit is contained in:
506
lib/Factory/BaseFactory.php
Normal file
506
lib/Factory/BaseFactory.php
Normal file
@@ -0,0 +1,506 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2024 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - https://xibosignage.com
|
||||
*
|
||||
* This file is part of Xibo.
|
||||
*
|
||||
* Xibo is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* Xibo is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Xibo\Factory;
|
||||
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Helper\SanitizerService;
|
||||
use Xibo\Service\BaseDependenciesService;
|
||||
use Xibo\Service\ConfigServiceInterface;
|
||||
use Xibo\Service\LogServiceInterface;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
/**
|
||||
* Class BaseFactory
|
||||
* @package Xibo\Factory
|
||||
*/
|
||||
class BaseFactory
|
||||
{
|
||||
/**
|
||||
* Count records last query
|
||||
* @var int
|
||||
*/
|
||||
protected $_countLast = 0;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
|
||||
/**
|
||||
* @var LogServiceInterface
|
||||
*/
|
||||
private $log;
|
||||
|
||||
/**
|
||||
* @var SanitizerService
|
||||
*/
|
||||
private $sanitizerService;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @var UserFactory
|
||||
*/
|
||||
private $userFactory;
|
||||
|
||||
/**
|
||||
* @var BaseDependenciesService
|
||||
*/
|
||||
private $baseDependenciesService;
|
||||
|
||||
/**
|
||||
* @param BaseDependenciesService $baseDependenciesService
|
||||
*/
|
||||
public function useBaseDependenciesService(BaseDependenciesService $baseDependenciesService)
|
||||
{
|
||||
$this->baseDependenciesService = $baseDependenciesService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Acl Dependencies
|
||||
* @param User $user
|
||||
* @param UserFactory $userFactory
|
||||
* @return $this
|
||||
*/
|
||||
public function setAclDependencies($user, $userFactory)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->userFactory = $userFactory;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Store
|
||||
* @return StorageServiceInterface
|
||||
*/
|
||||
protected function getStore()
|
||||
{
|
||||
return $this->baseDependenciesService->getStore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Log
|
||||
* @return LogServiceInterface
|
||||
*/
|
||||
protected function getLog()
|
||||
{
|
||||
return $this->baseDependenciesService->getLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SanitizerService
|
||||
*/
|
||||
protected function getSanitizerService()
|
||||
{
|
||||
return $this->baseDependenciesService->getSanitizer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sanitizer
|
||||
* @param $array
|
||||
* @return \Xibo\Support\Sanitizer\SanitizerInterface
|
||||
*/
|
||||
protected function getSanitizer($array)
|
||||
{
|
||||
return $this->getSanitizerService()->getSanitizer($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Xibo\Support\Validator\ValidatorInterface
|
||||
*/
|
||||
protected function getValidator()
|
||||
{
|
||||
return $this->getSanitizerService()->getValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get User
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get User Factory
|
||||
* @return UserFactory
|
||||
*/
|
||||
public function getUserFactory()
|
||||
{
|
||||
return $this->userFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
public function getDispatcher(): EventDispatcherInterface
|
||||
{
|
||||
return $this->baseDependenciesService->getDispatcher();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Xibo\Service\ConfigServiceInterface
|
||||
*/
|
||||
public function getConfig(): ConfigServiceInterface
|
||||
{
|
||||
return $this->baseDependenciesService->getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Count of records returned for the last query.
|
||||
* @return int
|
||||
*/
|
||||
public function countLast()
|
||||
{
|
||||
return $this->_countLast;
|
||||
}
|
||||
|
||||
/**
|
||||
* View Permission SQL
|
||||
* @param $entity
|
||||
* @param $sql
|
||||
* @param $params
|
||||
* @param $idColumn
|
||||
* @param null $ownerColumn
|
||||
* @param array $filterBy
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function viewPermissionSql(
|
||||
$entity,
|
||||
&$sql,
|
||||
&$params,
|
||||
$idColumn,
|
||||
$ownerColumn = null,
|
||||
$filterBy = [],
|
||||
$permissionFolderIdColumn = null
|
||||
) {
|
||||
$parsedBody = $this->getSanitizer($filterBy);
|
||||
$checkUserId = $parsedBody->getInt('userCheckUserId');
|
||||
|
||||
if ($checkUserId !== null) {
|
||||
$this->getLog()->debug(sprintf('Checking permissions against a specific user: %d', $checkUserId));
|
||||
$user = $this->getUserFactory()->getById($checkUserId);
|
||||
}
|
||||
else {
|
||||
$user = $this->getUser();
|
||||
|
||||
if ($user !== null)
|
||||
$this->getLog()->debug(sprintf('Checking permissions against the logged in user: ID: %d, Name: %s, UserType: %d', $user->userId, $user->userName, $user->userTypeId));
|
||||
}
|
||||
|
||||
$permissionSql = '';
|
||||
|
||||
// Has the user check been disabled? 0 = no it hasn't
|
||||
$performUserCheck = $parsedBody->getCheckbox('disableUserCheck') == 0;
|
||||
|
||||
if ($performUserCheck && !$user->isSuperAdmin()) {
|
||||
$permissionSql .= '
|
||||
AND (' . $idColumn . ' IN (
|
||||
SELECT `permission`.objectId
|
||||
FROM `permission`
|
||||
INNER JOIN `permissionentity`
|
||||
ON `permissionentity`.entityId = `permission`.entityId
|
||||
INNER JOIN `group`
|
||||
ON `group`.groupId = `permission`.groupId
|
||||
INNER JOIN `lkusergroup`
|
||||
ON `lkusergroup`.groupId = `group`.groupId
|
||||
INNER JOIN `user`
|
||||
ON lkusergroup.UserID = `user`.UserID
|
||||
WHERE `permissionentity`.entity = :permissionEntity
|
||||
AND `user`.userId = :currentUserId
|
||||
AND `permission`.view = 1
|
||||
UNION ALL
|
||||
SELECT `permission`.objectId
|
||||
FROM `permission`
|
||||
INNER JOIN `permissionentity`
|
||||
ON `permissionentity`.entityId = `permission`.entityId
|
||||
INNER JOIN `group`
|
||||
ON `group`.groupId = `permission`.groupId
|
||||
WHERE `permissionentity`.entity = :permissionEntity
|
||||
AND `group`.isEveryone = 1
|
||||
AND `permission`.view = 1
|
||||
)
|
||||
';
|
||||
|
||||
$params['permissionEntity'] = $entity;
|
||||
$params['currentUserId'] = $user->userId;
|
||||
|
||||
if ($ownerColumn != null) {
|
||||
$permissionSql .= ' OR ' . $ownerColumn . ' = :currentUserId2';
|
||||
$params['currentUserId2'] = $user->userId;
|
||||
}
|
||||
|
||||
// Home folders (only for folder entity)
|
||||
if ($entity === 'Xibo\Entity\Folder') {
|
||||
$permissionSql .= ' OR folder.folderId = :permissionsHomeFolderId';
|
||||
$permissionSql .= ' OR folder.permissionsFolderId = :permissionsHomeFolderId';
|
||||
$params['permissionsHomeFolderId'] = $this->getUser()->homeFolderId;
|
||||
}
|
||||
|
||||
// Group Admin?
|
||||
if ($user->userTypeId == 2 && $ownerColumn != null) {
|
||||
// OR the group admin and the owner of the media are in the same group
|
||||
$permissionSql .= '
|
||||
OR (
|
||||
SELECT COUNT(lkUserGroupId)
|
||||
FROM `lkusergroup`
|
||||
WHERE userId = ' . $ownerColumn . '
|
||||
AND groupId IN (
|
||||
SELECT groupId
|
||||
FROM `lkusergroup`
|
||||
WHERE userId = :currentUserId3
|
||||
)
|
||||
) > 0
|
||||
';
|
||||
|
||||
$params['currentUserId3'] = $user->userId;
|
||||
}
|
||||
|
||||
if ($permissionFolderIdColumn != null) {
|
||||
$permissionSql .= '
|
||||
OR ' . $permissionFolderIdColumn . ' IN (
|
||||
SELECT `permission`.objectId
|
||||
FROM `permission`
|
||||
INNER JOIN `permissionentity`
|
||||
ON `permissionentity`.entityId = `permission`.entityId
|
||||
INNER JOIN `group`
|
||||
ON `group`.groupId = `permission`.groupId
|
||||
INNER JOIN `lkusergroup`
|
||||
ON `lkusergroup`.groupId = `group`.groupId
|
||||
INNER JOIN `user`
|
||||
ON lkusergroup.UserID = `user`.UserID
|
||||
WHERE `permissionentity`.entity = :folderEntity
|
||||
AND `permission`.view = 1
|
||||
AND `user`.userId = :currentUserId
|
||||
UNION ALL
|
||||
SELECT `permission`.objectId
|
||||
FROM `permission`
|
||||
INNER JOIN `permissionentity`
|
||||
ON `permissionentity`.entityId = `permission`.entityId
|
||||
INNER JOIN `group`
|
||||
ON `group`.groupId = `permission`.groupId
|
||||
WHERE `permissionentity`.entity = :folderEntity
|
||||
AND `group`.isEveryone = 1
|
||||
AND `permission`.view = 1
|
||||
)
|
||||
';
|
||||
|
||||
$params['folderEntity'] = 'Xibo\Entity\Folder';
|
||||
}
|
||||
|
||||
$permissionSql .= ' )';
|
||||
|
||||
//$this->getLog()->debug('Permission SQL = %s', $permissionSql);
|
||||
}
|
||||
|
||||
// Set out params
|
||||
$sql = $sql . $permissionSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $variable
|
||||
* @return array
|
||||
*/
|
||||
protected function parseComparisonOperator($variable)
|
||||
{
|
||||
$operator = '=';
|
||||
$allowedOperators = [
|
||||
'less-than' => '<',
|
||||
'greater-than' => '>',
|
||||
'less-than-equal' => '<=',
|
||||
'greater-than-equal' => '>='
|
||||
];
|
||||
|
||||
if (stripos($variable, '|') !== false) {
|
||||
$variable = explode('|', $variable);
|
||||
|
||||
if (array_key_exists($variable[0], $allowedOperators)) {
|
||||
$operator = $allowedOperators[$variable[0]];
|
||||
}
|
||||
|
||||
$variable = $variable[1];
|
||||
}
|
||||
|
||||
return [
|
||||
'operator' => $operator,
|
||||
'variable' => $variable
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name filter for all factories to use.
|
||||
*
|
||||
* @param string $tableName Table name
|
||||
* @param string $tableColumn Column with the name
|
||||
* @param array $terms An Array exploded by "," of the search names
|
||||
* @param string $body Current SQL body passed by reference
|
||||
* @param array $params Array of parameters passed by reference
|
||||
* @param bool $useRegex flag to match against a regex pattern
|
||||
*/
|
||||
public function nameFilter(
|
||||
$tableName,
|
||||
$tableColumn,
|
||||
$terms,
|
||||
&$body,
|
||||
&$params,
|
||||
$useRegex = false,
|
||||
$logicalOperator = 'OR'
|
||||
) {
|
||||
$i = 0;
|
||||
|
||||
$tableAndColumn = $tableName . '.' . $tableColumn;
|
||||
// filter empty array elements, in an attempt to better handle spaces after `,`.
|
||||
$filteredNames = array_filter($terms, function ($element) {
|
||||
return is_string($element) && '' !== trim($element);
|
||||
});
|
||||
|
||||
foreach ($filteredNames as $searchName) {
|
||||
// Trim/Sanitise
|
||||
$searchName = trim($searchName);
|
||||
|
||||
// Discard any incompatible
|
||||
if (empty(ltrim($searchName, '-')) || empty($searchName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validate the logical operator
|
||||
if (!in_array($logicalOperator, ['AND', 'OR'])) {
|
||||
$this->getLog()->error('Invalid logical operator ' . $logicalOperator);
|
||||
return;
|
||||
}
|
||||
|
||||
// increase here, after we expect additional sql to be added.
|
||||
$i++;
|
||||
|
||||
// Not like, or like?
|
||||
if (str_starts_with($searchName, '-')) {
|
||||
if ($i === 1) {
|
||||
$body .= ' AND ( '.$tableAndColumn.' NOT RLIKE (:search'.$i.') ';
|
||||
} else {
|
||||
$body .= ' ' . $logicalOperator . ' '.$tableAndColumn.' NOT RLIKE (:search'.$i.') ';
|
||||
}
|
||||
$params['search' . $i] = $useRegex ? ltrim(($searchName), '-') : preg_quote(ltrim(($searchName), '-'));
|
||||
} else {
|
||||
if ($i === 1) {
|
||||
$body .= ' AND ( '.$tableAndColumn.' RLIKE (:search'.$i.') ';
|
||||
} else {
|
||||
$body .= ' ' . $logicalOperator . ' '.$tableAndColumn.' RLIKE (:search'.$i.') ';
|
||||
}
|
||||
$params['search' . $i] = $useRegex ? $searchName : preg_quote($searchName);
|
||||
}
|
||||
}
|
||||
|
||||
// append closing parenthesis only if we added any sql.
|
||||
if (!empty($filteredNames) && $i > 0) {
|
||||
$body .= ' ) ';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tags An array of tags
|
||||
* @param string $lkTagTable name of the lktag table
|
||||
* @param string $lkTagTableIdColumn name of the id column in the lktag table
|
||||
* @param string $idColumn name of the id column in main table
|
||||
* @param string $logicalOperator AND or OR logical operator passed from Factory
|
||||
* @param string $operator exactTags passed from factory, determines if the search is LIKE or =
|
||||
* @param string $body Current SQL body passed by reference
|
||||
* @param array $params Array of parameters passed by reference
|
||||
*/
|
||||
public function tagFilter(
|
||||
$tags,
|
||||
$lkTagTable,
|
||||
$lkTagTableIdColumn,
|
||||
$idColumn,
|
||||
$logicalOperator,
|
||||
$operator,
|
||||
$notTags,
|
||||
&$body,
|
||||
&$params
|
||||
) {
|
||||
$i = 0;
|
||||
$paramName = ($notTags) ? 'notTags' : 'tags';
|
||||
$paramValueName = ($notTags) ? 'notValue' : 'value';
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$i++;
|
||||
|
||||
$tagV = explode('|', $tag);
|
||||
|
||||
// search tag without value
|
||||
if (!isset($tagV[1])) {
|
||||
if ($i == 1) {
|
||||
$body .= ' WHERE `tag` ' . $operator . ' :'. $paramName . $i;
|
||||
} else {
|
||||
$body .= ' OR ' . ' `tag` ' . $operator . ' :' . $paramName . $i;
|
||||
}
|
||||
|
||||
if ($operator === '=') {
|
||||
$params[$paramName . $i] = $tag;
|
||||
} else {
|
||||
$params[$paramName . $i] = '%' . $tag . '%';
|
||||
}
|
||||
// search tag only by value
|
||||
} elseif ($tagV[0] == '') {
|
||||
if ($i == 1) {
|
||||
$body .= ' WHERE `value` ' . $operator . ' :' . $paramValueName . $i;
|
||||
} else {
|
||||
$body .= ' OR ' . ' `value` ' . $operator . ' :' . $paramValueName . $i;
|
||||
}
|
||||
|
||||
if ($operator === '=') {
|
||||
$params[$paramValueName . $i] = $tagV[1];
|
||||
} else {
|
||||
$params[$paramValueName . $i] = '%' . $tagV[1] . '%';
|
||||
}
|
||||
// search tag by both tag and value
|
||||
} else {
|
||||
if ($i == 1) {
|
||||
$body .= ' WHERE `tag` ' . $operator . ' :' . $paramName . $i .
|
||||
' AND value ' . $operator . ' :' . $paramValueName . $i;
|
||||
} else {
|
||||
$body .= ' OR ' . ' `tag` ' . $operator . ' :' . $paramName . $i .
|
||||
' AND value ' . $operator . ' :' . $paramValueName . $i;
|
||||
}
|
||||
|
||||
if ($operator === '=') {
|
||||
$params[$paramName . $i] = $tagV[0];
|
||||
$params[$paramValueName . $i] = $tagV[1];
|
||||
} else {
|
||||
$params[$paramName . $i] = '%' . $tagV[0] . '%';
|
||||
$params[$paramValueName . $i] = '%' . $tagV[1] . '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($logicalOperator === 'AND' && count($tags) > 1 && !$notTags) {
|
||||
$body .= ' GROUP BY ' . $lkTagTable . '.' . $idColumn . ' HAVING count(' . $lkTagTable .'.'. $lkTagTableIdColumn .') = ' . count($tags);//@phpcs:ignore
|
||||
}
|
||||
|
||||
$body .= ' ) ';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user