snapshot of https://github.com/espocrm/espocrm.git (master, 2026-09-18; blobs > 131072B omitted)
Some checks failed
Test / Test on PHP 8.3 (push) Failing after 5s
Test / Test on PHP 8.4 (push) Failing after 4s
Test / Test on PHP 8.5 (push) Failing after 3s
TypeScript static analysis / TypeScript check (push) Failing after 14s
Test Integration on MySQL / Test on PHP 8.3 (push) Failing after 2s
Test Integration on MySQL / Test on PHP 8.5 (push) Failing after 0s
Test Integration on PostgreSQL / Test on PHP 8.4 fix (push) Failing after 1s
Test Integration on PostgreSQL / Test on PHP 8.4 master (push) Failing after 1s
Some checks failed
Test / Test on PHP 8.3 (push) Failing after 5s
Test / Test on PHP 8.4 (push) Failing after 4s
Test / Test on PHP 8.5 (push) Failing after 3s
TypeScript static analysis / TypeScript check (push) Failing after 14s
Test Integration on MySQL / Test on PHP 8.3 (push) Failing after 2s
Test Integration on MySQL / Test on PHP 8.5 (push) Failing after 0s
Test Integration on PostgreSQL / Test on PHP 8.4 fix (push) Failing after 1s
Test Integration on PostgreSQL / Test on PHP 8.4 master (push) Failing after 1s
This commit is contained in:
144
tests/unit/Espo/Core/Select/AccessControl/FilterFactoryTest.php
Normal file
144
tests/unit/Espo/Core/Select/AccessControl/FilterFactoryTest.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\AccessControl;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\AclManager;
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\AccessControl\FilterFactory;
|
||||
use Espo\Core\Select\AccessControl\Filters\OnlyOwn;
|
||||
use Espo\Core\Select\Helpers\FieldHelper;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\User;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FilterFactoryTest extends TestCase
|
||||
{
|
||||
private $aclManager;
|
||||
private $acl;
|
||||
private $metadata;
|
||||
private $injectableFactory;
|
||||
private $factory;
|
||||
private $user;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->aclManager = $this->createMock(AclManager::class);
|
||||
$this->acl = $this->createMock(Acl::class);
|
||||
|
||||
$this->factory = new FilterFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata,
|
||||
$this->aclManager,
|
||||
$this->acl,
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(null, OnlyOwn::class, 'onlyOwn');
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest('SomeClass', OnlyOwn::class, 'onlyOwn');
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className, string $defaultClassName, string $name)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'accessControlFilterClassNameMap', $name], null, $className],
|
||||
]);
|
||||
|
||||
$className = $className ?? $defaultClassName;
|
||||
|
||||
$object = $this->createMock($defaultClassName);
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $this->user)
|
||||
->bindInstance(AclManager::class, $this->aclManager)
|
||||
->bindInstance(Acl::class, $this->acl);
|
||||
|
||||
$binder
|
||||
->for($className)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$binder
|
||||
->for(FieldHelper::class)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bindingContainer = new BindingContainer($bindingData);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->exactly(1))
|
||||
->method('createWithBinding')
|
||||
->with($className, $bindingContainer)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create(
|
||||
$entityType,
|
||||
$this->user,
|
||||
$name
|
||||
);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->factory->has($entityType, $name)
|
||||
);
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'accessControlFilterClassNameMap', 'badName'], null, null],
|
||||
]);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->factory->has($entityType, 'badName')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\AccessControl;
|
||||
|
||||
use Espo\Core\Utils\Acl\UserAclManagerProvider;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\AclManager;
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Portal\Acl as PortalAcl;
|
||||
use Espo\Core\Portal\AclManager as PortalAclManager;
|
||||
use Espo\Core\Select\AccessControl\DefaultFilterResolver;
|
||||
use Espo\Core\Select\AccessControl\DefaultPortalFilterResolver;
|
||||
use Espo\Core\Select\AccessControl\FilterResolverFactory;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\User;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FilterResolverFactoryTest extends TestCase
|
||||
{
|
||||
private $injectableFactory;
|
||||
private $metadata;
|
||||
private $user;
|
||||
private $aclManager;
|
||||
private $acl;
|
||||
private $factory;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->aclManager = $this->createMock(AclManager::class);
|
||||
$this->acl = $this->createMock(Acl::class);
|
||||
|
||||
$this->factory = new FilterResolverFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata,
|
||||
$this->aclManager,
|
||||
$this->acl,
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(null);
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest('SomeClass');
|
||||
}
|
||||
|
||||
public function testCreatePortal()
|
||||
{
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('isPortal')
|
||||
->willReturn(true);
|
||||
|
||||
$this->prepareFactoryTest(null);
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
if (!$this->user->isPortal()) {
|
||||
$defaultClassName = DefaultFilterResolver::class;
|
||||
} else {
|
||||
$defaultClassName = DefaultPortalFilterResolver::class;
|
||||
}
|
||||
|
||||
$this->metadata
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with([
|
||||
'selectDefs', $entityType,
|
||||
!$this->user->isPortal() ?
|
||||
'accessControlFilterResolverClassName':
|
||||
'portalAccessControlFilterResolverClassName'
|
||||
])
|
||||
->willReturn($className);
|
||||
|
||||
$className = $className ?? $defaultClassName;
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $this->user)
|
||||
->bindInstance(AclManager::class, $this->aclManager)
|
||||
->bindInstance(Acl::class, $this->acl);
|
||||
|
||||
|
||||
if ($this->user->isPortal()) {
|
||||
$binder->bindInstance(PortalAcl::class, $this->acl);
|
||||
$binder->bindInstance(PortalAclManager::class, $this->aclManager);
|
||||
}
|
||||
|
||||
$binder
|
||||
->for($className)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bindingContainer = new BindingContainer($bindingData);
|
||||
|
||||
$object = $this->createMock($defaultClassName);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWithBinding')
|
||||
->with($className, $bindingContainer)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create($entityType, $this->user);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
}
|
||||
}
|
||||
158
tests/unit/Espo/Core/Select/AccessControl/FilterResolverTest.php
Normal file
158
tests/unit/Espo/Core/Select/AccessControl/FilterResolverTest.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\AccessControl;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\Portal\Acl as AclPortal;
|
||||
use Espo\Core\Select\AccessControl\DefaultFilterResolver;
|
||||
use Espo\Core\Select\AccessControl\DefaultPortalFilterResolver;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FilterResolverTest extends TestCase
|
||||
{
|
||||
private $acl;
|
||||
private $aclPortal;
|
||||
private $entityType;
|
||||
private $resolver;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->acl = $this->createMock(Acl::class);
|
||||
$this->aclPortal = $this->createMock(AclPortal::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
}
|
||||
|
||||
public function testResolveRegularOnlyOwn()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'onlyOwn',
|
||||
$this->initResolveTest(false, 'checkReadOnlyOwn')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolveRegularOnlyTeam()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'onlyTeam',
|
||||
$this->initResolveTest(false, 'checkReadOnlyTeam')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolveRegularNo()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'no',
|
||||
$this->initResolveTest(false, 'checkReadNo')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolvePortalOnlyOwn()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'portalOnlyOwn',
|
||||
$this->initResolveTest(true, 'checkReadOnlyOwn')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolvePortalOnlyAccount()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'portalOnlyAccount',
|
||||
$this->initResolveTest(true, 'checkReadOnlyAccount')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolvePortalOnlyContact()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'portalOnlyContact',
|
||||
$this->initResolveTest(true, 'checkReadOnlyContact')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolvePortalNo()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'no',
|
||||
$this->initResolveTest(true, 'checkReadNo')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolveAll()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'all',
|
||||
$this->initResolveTest(false, 'checkReadAll')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResolvePortalAll()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'portalAll',
|
||||
$this->initResolveTest(true, 'checkReadAll')
|
||||
);
|
||||
}
|
||||
|
||||
protected function initResolveTest(bool $isPortal = false, ?string $method = null): ?string
|
||||
{
|
||||
$acl = $this->acl;
|
||||
|
||||
if ($isPortal) {
|
||||
$acl = $this->aclPortal;
|
||||
}
|
||||
|
||||
if (!$isPortal) {
|
||||
$this->resolver = new DefaultFilterResolver(
|
||||
$this->entityType,
|
||||
$acl
|
||||
);
|
||||
}
|
||||
|
||||
if ($isPortal) {
|
||||
$this->resolver = new DefaultPortalFilterResolver(
|
||||
$this->entityType,
|
||||
$acl
|
||||
);
|
||||
}
|
||||
|
||||
if ($method) {
|
||||
$acl
|
||||
->expects($this->any())
|
||||
->method($method)
|
||||
->with($this->entityType)
|
||||
->willReturn(true);
|
||||
}
|
||||
|
||||
return $this->resolver->resolve();
|
||||
}
|
||||
}
|
||||
348
tests/unit/Espo/Core/Select/AccessControl/FiltersTest.php
Normal file
348
tests/unit/Espo/Core/Select/AccessControl/FiltersTest.php
Normal file
@@ -0,0 +1,348 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\AccessControl;
|
||||
|
||||
use Espo\Core\Field\LinkMultiple;
|
||||
use Espo\Core\Field\LinkMultipleItem;
|
||||
use Espo\Core\Portal\Acl\OwnershipChecker\MetadataProvider;
|
||||
use Espo\Core\Select\AccessControl\Filter as AccessControlFilter;
|
||||
use Espo\Core\Select\AccessControl\Filters\No;
|
||||
use Espo\Core\Select\AccessControl\Filters\PortalOnlyAccount;
|
||||
use Espo\Core\Select\AccessControl\Filters\PortalOnlyContact;
|
||||
use Espo\Core\Select\AccessControl\Filters\PortalOnlyOwn;
|
||||
use Espo\Core\Select\Helpers\FieldHelper;
|
||||
use Espo\Core\Select\Helpers\RelationQueryHelper;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Modules\Crm\Entities\Account;
|
||||
use Espo\Modules\Crm\Entities\Contact;
|
||||
use Espo\ORM\Defs;
|
||||
use Espo\ORM\Defs\RelationDefs;
|
||||
use Espo\ORM\Query\Part\Where\OrGroup;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use Espo\ORM\Type\RelationType;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FiltersTest extends TestCase
|
||||
{
|
||||
private $queryBuilder;
|
||||
private $fieldHelper;
|
||||
private $user;
|
||||
private $entityType;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
$this->fieldHelper = $this->createMock(FieldHelper::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$this->user->set('id', 'user-id');
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn('user-id');
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getTeamIdList')
|
||||
->willReturn(['team-id']);
|
||||
}
|
||||
|
||||
public function testNo(): void
|
||||
{
|
||||
$filter = $this->createFilter(No::class);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with([
|
||||
'id' => null,
|
||||
]);
|
||||
|
||||
$filter->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testPortalOnlyAccount1(): void
|
||||
{
|
||||
$defs = $this->createMock(Defs::class);
|
||||
$metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
|
||||
$queryHelper = new RelationQueryHelper($defs);
|
||||
|
||||
$filter = new PortalOnlyAccount(
|
||||
'Test',
|
||||
$this->user,
|
||||
$this->fieldHelper,
|
||||
$metadataProvider,
|
||||
$queryHelper
|
||||
);
|
||||
|
||||
$metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getContactLink')
|
||||
->willReturn(
|
||||
RelationDefs::fromRaw([
|
||||
'type' => RelationType::BELONGS_TO_PARENT,
|
||||
'entityList' => [Contact::ENTITY_TYPE],
|
||||
], 'contact')
|
||||
);
|
||||
|
||||
$metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getAccountLink')
|
||||
->willReturn(
|
||||
RelationDefs::fromRaw([
|
||||
'type' => RelationType::MANY_MANY,
|
||||
'entity' => [Account::ENTITY_TYPE],
|
||||
'midKeys' => ['nId', 'fId'],
|
||||
'relationName' => 'TestAccount'
|
||||
], 'account')
|
||||
);
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getAccounts')
|
||||
->willReturn(LinkMultiple::create([
|
||||
LinkMultipleItem::create('account-id')
|
||||
]));
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getContactId')
|
||||
->willReturn('contact-id');
|
||||
|
||||
$this->initHelperMethods([
|
||||
['hasCreatedByField', true],
|
||||
]);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with(
|
||||
$this->callback(function ($where) {
|
||||
if (!$where instanceof OrGroup) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($where->getRawValue()[0]['id=s'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $where->getItemCount() === 3;
|
||||
})
|
||||
)
|
||||
->willReturn($this->queryBuilder);
|
||||
|
||||
$filter->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testPortalOnlyAccount2(): void
|
||||
{
|
||||
$defs = $this->createMock(Defs::class);
|
||||
$metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
|
||||
$queryHelper = new RelationQueryHelper($defs);
|
||||
|
||||
$filter = new PortalOnlyAccount(
|
||||
'Test',
|
||||
$this->user,
|
||||
$this->fieldHelper,
|
||||
$metadataProvider,
|
||||
$queryHelper
|
||||
);
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getLinkMultipleIdList')
|
||||
->with('accounts')
|
||||
->willReturn([]);
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->with('contactId')
|
||||
->willReturn(null);
|
||||
|
||||
$this->initHelperMethods([
|
||||
['hasCreatedByField', false],
|
||||
]);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with([
|
||||
'id' => null,
|
||||
]);
|
||||
|
||||
$filter->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testPortalOnlyContact1(): void
|
||||
{
|
||||
$defs = $this->createMock(Defs::class);
|
||||
$metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
|
||||
$queryHelper = new RelationQueryHelper($defs);
|
||||
|
||||
$filter = new PortalOnlyContact(
|
||||
'Test',
|
||||
$this->user,
|
||||
$this->fieldHelper,
|
||||
$metadataProvider,
|
||||
$queryHelper
|
||||
);
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getContactId')
|
||||
->willReturn('contact-id');
|
||||
|
||||
$this->initHelperMethods([
|
||||
['hasCreatedByField', true],
|
||||
]);
|
||||
|
||||
$metadataProvider
|
||||
->expects($this->once())
|
||||
->method('getContactLink')
|
||||
->willReturn(
|
||||
RelationDefs::fromRaw([
|
||||
'type' => RelationType::BELONGS_TO,
|
||||
'entity' => Contact::ENTITY_TYPE,
|
||||
], 'contact')
|
||||
);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with(
|
||||
$this->callback(function ($where) {
|
||||
return $where instanceof OrGroup &&
|
||||
$where->getItemCount() === 2;
|
||||
})
|
||||
)
|
||||
->willReturn($this->queryBuilder);
|
||||
|
||||
$filter->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testPortalOnlyContact2()
|
||||
{
|
||||
$defs = $this->createMock(Defs::class);
|
||||
$metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
|
||||
$queryHelper = new RelationQueryHelper($defs);
|
||||
|
||||
$filter = new PortalOnlyContact(
|
||||
'Test',
|
||||
$this->user,
|
||||
$this->fieldHelper,
|
||||
$metadataProvider,
|
||||
$queryHelper
|
||||
);
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->with('contactId')
|
||||
->willReturn(null);
|
||||
|
||||
$this->initHelperMethods([
|
||||
['hasCreatedByField', false],
|
||||
]);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with([
|
||||
'id' => null,
|
||||
])
|
||||
->willReturn($this->queryBuilder);
|
||||
|
||||
$filter->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testPortalOnlyOwn1()
|
||||
{
|
||||
$filter = $this->createFilter(PortalOnlyOwn::class);
|
||||
|
||||
$this->initHelperMethods([
|
||||
['hasCreatedByField', true],
|
||||
]);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with([
|
||||
'createdById' => $this->user->getId(),
|
||||
])
|
||||
->willReturn($this->queryBuilder);
|
||||
|
||||
$filter->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testPortalOnlyOwn2()
|
||||
{
|
||||
$filter = $this->createFilter(PortalOnlyOwn::class);
|
||||
|
||||
$this->initHelperMethods([
|
||||
['hasCreatedByField', false],
|
||||
]);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with([
|
||||
'id' => null,
|
||||
])
|
||||
->willReturn($this->queryBuilder);
|
||||
|
||||
$filter->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
protected function initHelperMethods(array $map)
|
||||
{
|
||||
foreach ($map as $i => $item) {
|
||||
$this->fieldHelper
|
||||
->expects($this->once())
|
||||
->method($item[0])
|
||||
->willReturn($item[1]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function createFilter(string $className): AccessControlFilter
|
||||
{
|
||||
return new $className(
|
||||
$this->user,
|
||||
$this->fieldHelper
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
|
||||
|
||||
use Espo\Core\Select\AccessControl\Applier as AccessControlFilterApplier;
|
||||
use Espo\Core\Select\AccessControl\Filter as AccessControlFilter;
|
||||
use Espo\Core\Select\AccessControl\FilterFactory as AccessControlFilterFactory;
|
||||
use Espo\Core\Select\AccessControl\FilterResolver;
|
||||
use Espo\Core\Select\AccessControl\FilterResolverFactory as AccessControlFilterResolverFactory;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AccessControlFilterApplierTest extends TestCase
|
||||
{
|
||||
private $filterFactory;
|
||||
private $filterResolverFactory;
|
||||
private $user;
|
||||
private $queryBuilder;
|
||||
private $filterResolver;
|
||||
private $filter;
|
||||
private $mandatoryFilter;
|
||||
private $entityType;
|
||||
private $applier;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->filterFactory = $this->createMock(AccessControlFilterFactory::class);
|
||||
$this->filterResolverFactory = $this->createMock(AccessControlFilterResolverFactory::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
$this->filterResolver = $this->createMock(FilterResolver::class);
|
||||
$this->filter = $this->createMock(AccessControlFilter::class);
|
||||
$this->mandatoryFilter = $this->createMock(AccessControlFilter::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->applier = new AccessControlFilterApplier(
|
||||
entityType: $this->entityType,
|
||||
user: $this->user,
|
||||
accessControlFilterFactory: $this->filterFactory,
|
||||
accessControlFilterResolverFactory: $this->filterResolverFactory,
|
||||
);
|
||||
}
|
||||
|
||||
public function testApply1()
|
||||
{
|
||||
$this->initApplierTest(true, true);
|
||||
|
||||
$this->applier->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testApply2()
|
||||
{
|
||||
$this->initApplierTest(true, false);
|
||||
|
||||
$this->applier->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
public function testApply3()
|
||||
{
|
||||
$this->initApplierTest(false, false);
|
||||
|
||||
$this->applier->apply($this->queryBuilder);
|
||||
}
|
||||
|
||||
protected function initApplierTest(bool $resolve, bool $hasFilter)
|
||||
{
|
||||
$this->filterResolverFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $this->user)
|
||||
->willReturn($this->filterResolver);
|
||||
|
||||
$filterName = null;
|
||||
|
||||
if ($resolve) {
|
||||
$filterName = 'test';
|
||||
}
|
||||
|
||||
$this->filterResolver
|
||||
->expects($this->once())
|
||||
->method('resolve')
|
||||
->willReturn($filterName);
|
||||
|
||||
if (!$resolve) {
|
||||
$this->filterFactory
|
||||
->expects($this->never())
|
||||
->method('has');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->filterFactory
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with($this->entityType, $filterName)
|
||||
->willReturn($hasFilter);
|
||||
|
||||
if (!$hasFilter) {
|
||||
$this->expectException(\RuntimeException::class);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->filterFactory
|
||||
->expects($this->exactly(2))
|
||||
->method('create')
|
||||
->willReturnMap([
|
||||
[$this->entityType, $this->user, 'mandatory', $this->mandatoryFilter],
|
||||
[$this->entityType, $this->user, $filterName, $this->filter],
|
||||
]);
|
||||
|
||||
$this->filter
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with($this->queryBuilder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
|
||||
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Select\Bool\Applier as BoolFilterListApplier;
|
||||
use Espo\Core\Select\Bool\Filter as BoolFilter;
|
||||
use Espo\Core\Select\Bool\FilterFactory as BoolFilterFactory;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\Part\Where\OrGroupBuilder;
|
||||
use Espo\ORM\Query\Part\WhereClause;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class BoolFilterListApplierTest extends TestCase
|
||||
{
|
||||
private $boolFilterFactory;
|
||||
private $user;
|
||||
private $queryBuilder;
|
||||
private $entityType;
|
||||
private $applier;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->boolFilterFactory = $this->createMock(BoolFilterFactory::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->applier = new BoolFilterListApplier(
|
||||
entityType: $this->entityType,
|
||||
user: $this->user,
|
||||
boolFilterFactory: $this->boolFilterFactory,
|
||||
);
|
||||
}
|
||||
|
||||
public function testApply1()
|
||||
{
|
||||
$boolFilterList = ['test1', 'test2'];
|
||||
|
||||
$filter1 = $this->createFilterMock(['test' => '1']);
|
||||
$filter2 = $this->createFilterMock(['test' => '2']);
|
||||
|
||||
$this->initApplierTest($boolFilterList, [$filter1, $filter2], [true, true]);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where');
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $boolFilterList);
|
||||
}
|
||||
|
||||
public function testApply2()
|
||||
{
|
||||
$boolFilterList = ['test1'];
|
||||
|
||||
$filter1 = $this->createFilterMock(['test' => '1']);
|
||||
|
||||
$this->initApplierTest($boolFilterList, [$filter1], [true]);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where');
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $boolFilterList);
|
||||
}
|
||||
|
||||
public function testApply3()
|
||||
{
|
||||
$boolFilterList = ['test1'];
|
||||
|
||||
$this->initApplierTest($boolFilterList, [null], [false]);
|
||||
|
||||
$this->expectException(BadRequest::class);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $boolFilterList);
|
||||
}
|
||||
|
||||
protected function initApplierTest(array $filterNameList, array $filterList, array $hasList)
|
||||
{
|
||||
$hasMap = [];
|
||||
$createMap = [];
|
||||
|
||||
foreach ($filterNameList as $i => $filterName) {
|
||||
$hasMap[] = [$this->entityType, $filterName, $hasList[$i]];
|
||||
|
||||
if (!$hasList[$i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$createMap[] = [$this->entityType, $this->user, $filterName, $filterList[$i]];
|
||||
}
|
||||
|
||||
$this->boolFilterFactory
|
||||
->expects($this->any())
|
||||
->method('has')
|
||||
->willReturnMap($hasMap);
|
||||
|
||||
$this->boolFilterFactory
|
||||
->expects($this->any())
|
||||
->method('create')
|
||||
->willReturnMap($createMap);
|
||||
}
|
||||
|
||||
protected function createFilterMock(array $rawWhereClause): BoolFilter
|
||||
{
|
||||
$filter = $this->createMock(BoolFilter::class);
|
||||
|
||||
$whereClause = $this->createMock(WhereClause::class);
|
||||
|
||||
$whereClause
|
||||
->expects($this->any())
|
||||
->method('getRawValue')
|
||||
->willReturn($rawWhereClause);
|
||||
|
||||
$filter
|
||||
->expects($this->any())
|
||||
->method('apply')
|
||||
->with($this->queryBuilder, $this->isInstanceOf(OrGroupBuilder::class));
|
||||
|
||||
return $filter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
|
||||
|
||||
use Espo\Core\Acl\SystemRestriction;
|
||||
use Espo\Core\AclManager;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\Part\OrderList;
|
||||
use Espo\ORM\Query\Part\Order;
|
||||
use Espo\Core\Select\Order\Applier as OrderApplier;
|
||||
use Espo\Core\Select\Order\Item;
|
||||
use Espo\Core\Select\Order\ItemConverter;
|
||||
use Espo\Core\Select\Order\ItemConverterFactory;
|
||||
use Espo\Core\Select\Order\MetadataProvider;
|
||||
use Espo\Core\Select\Order\Orderer;
|
||||
use Espo\Core\Select\Order\OrdererFactory;
|
||||
use Espo\Core\Select\Order\Params as OrderParams;
|
||||
use Espo\Core\Select\SearchParams;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class OrderApplierTest extends TestCase
|
||||
{
|
||||
private ?OrdererFactory $ordererFactory = null;
|
||||
|
||||
private $metadataProvider;
|
||||
private $itemConverterFactory;
|
||||
private $queryBuilder;
|
||||
private $params;
|
||||
private $entityType;
|
||||
private $applier;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
$this->itemConverterFactory = $this->createMock(ItemConverterFactory::class);
|
||||
$this->ordererFactory = $this->createMock(OrdererFactory::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
$this->params = $this->createMock(OrderParams::class);
|
||||
|
||||
$aclManager = $this->createMock(AclManager::class);
|
||||
$user = $this->createMock(User::class);
|
||||
|
||||
$restriction = $this->createMock(SystemRestriction::class);
|
||||
$restriction
|
||||
->method('checkFieldRead')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->applier = new OrderApplier(
|
||||
entityType: $this->entityType,
|
||||
metadataProvider: $this->metadataProvider,
|
||||
itemConverterFactory: $this->itemConverterFactory,
|
||||
ordererFactory: $this->ordererFactory,
|
||||
aclManager: $aclManager,
|
||||
user: $user,
|
||||
systemRestriction: $restriction,
|
||||
);
|
||||
}
|
||||
|
||||
public function testApplyDefault()
|
||||
{
|
||||
$order = SearchParams::ORDER_DESC;
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forceDefault')
|
||||
->willReturn(true);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrder')
|
||||
->willReturn($order);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getDefaultOrderBy')
|
||||
->with($this->entityType)
|
||||
->willReturn('testField');
|
||||
|
||||
$this->initApplyOrderTest('testField', $order, 'varchar');
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->params);
|
||||
}
|
||||
|
||||
public function testApply1()
|
||||
{
|
||||
$order = SearchParams::ORDER_DESC;
|
||||
$orderBy = 'testField';
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forceDefault')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrder')
|
||||
->willReturn($order);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrderBy')
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getDefaultOrderBy')
|
||||
->with($this->entityType)
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->initApplyOrderTest($orderBy, $order, 'varchar');
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->params);
|
||||
}
|
||||
|
||||
public function testApplyWithConverter()
|
||||
{
|
||||
$order = SearchParams::ORDER_DESC;
|
||||
$orderBy = 'testField';
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forceDefault')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrder')
|
||||
->willReturn($order);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrderBy')
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getDefaultOrderBy')
|
||||
->with($this->entityType)
|
||||
->willReturn($orderBy);
|
||||
|
||||
$converterResult = OrderList::create([
|
||||
Order::fromString('hello')->withDesc(),
|
||||
]);
|
||||
|
||||
$this->initApplyOrderTest($orderBy, $order, 'varchar', $converterResult);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->params);
|
||||
}
|
||||
|
||||
public function testApplyNotExisting()
|
||||
{
|
||||
$order = SearchParams::ORDER_DESC;
|
||||
$orderBy = 'testField';
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forceDefault')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrder')
|
||||
->willReturn($order);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrderBy')
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getDefaultOrderBy')
|
||||
->with($this->entityType)
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->initApplyOrderTest($orderBy, $order, 'varchar', null, true);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->params);
|
||||
}
|
||||
|
||||
public function testApplyWithOrderer()
|
||||
{
|
||||
$order = SearchParams::ORDER_DESC;
|
||||
$orderBy = 'testField';
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forceDefault')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrder')
|
||||
->willReturn($order);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrderBy')
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->ordererFactory
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn(true);
|
||||
|
||||
$orderer = $this->createMock(Orderer::class);
|
||||
|
||||
$this->ordererFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn($orderer);
|
||||
|
||||
$orderer
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with($this->queryBuilder, Item::create($orderBy, $order));
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->params);
|
||||
}
|
||||
|
||||
protected function initApplyOrderTest(
|
||||
string $orderBy,
|
||||
string $order,
|
||||
string $fieldType,
|
||||
?OrderList $converterResult = null,
|
||||
bool $notExisting = false
|
||||
) {
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getFieldType')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn($fieldType);
|
||||
|
||||
$this->itemConverterFactory
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn(
|
||||
(bool) $converterResult
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('hasAttribute')
|
||||
->willReturnMap(
|
||||
[
|
||||
[$this->entityType, $orderBy, !$notExisting],
|
||||
[$this->entityType, 'id', true],
|
||||
]
|
||||
);
|
||||
|
||||
if ($converterResult) {
|
||||
$converter = $this->createMock(ItemConverter::class);
|
||||
|
||||
$this->itemConverterFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn($converter);
|
||||
|
||||
$item = Item::create($orderBy, $order);
|
||||
|
||||
$converter
|
||||
->expects($this->once())
|
||||
->method('convert')
|
||||
->with($item)
|
||||
->willReturn($converterResult);
|
||||
} else {
|
||||
if ($notExisting) {
|
||||
$this->expectException(BadRequest::class);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->once())
|
||||
->method('isAttributeParamUniqueTrue')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn(false);
|
||||
}
|
||||
|
||||
$expectedOrderBy = ($converterResult ? $this->orderListToArray($converterResult): null)
|
||||
?? [[$orderBy, $order]];
|
||||
|
||||
$expectedOrderBy[] = ['id', $order];
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('order')
|
||||
->with($expectedOrderBy);
|
||||
}
|
||||
|
||||
private function orderListToArray(OrderList $orderList): array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ($orderList as $order) {
|
||||
$list[] = [
|
||||
$order->getExpression()->getValue(),
|
||||
$order->getDirection(),
|
||||
];
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
|
||||
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Select\Primary\Applier as PrimaryFilterApplier;
|
||||
use Espo\Core\Select\Primary\Filter as PrimaryFilter;
|
||||
use Espo\Core\Select\Primary\FilterFactory as PrimaryFilterFactory;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class PrimaryFilterApplierTest extends TestCase
|
||||
{
|
||||
private $filterFactory;
|
||||
private $user;
|
||||
private $queryBuilder;
|
||||
private $entityType;
|
||||
private $applier;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->filterFactory = $this->createMock(PrimaryFilterFactory::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->applier = new PrimaryFilterApplier(
|
||||
entityType: $this->entityType,
|
||||
user: $this->user,
|
||||
primaryFilterFactory: $this->filterFactory,
|
||||
);
|
||||
}
|
||||
|
||||
public function testApply1()
|
||||
{
|
||||
$filterName = 'test';
|
||||
|
||||
$filter = $this->createMock(PrimaryFilter::class);
|
||||
|
||||
$filter
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with($this->queryBuilder);
|
||||
|
||||
$this->filterFactory
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with($this->entityType, $filterName)
|
||||
->willReturn(true);
|
||||
|
||||
$this->filterFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $this->user, $filterName)
|
||||
->willReturn($filter);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $filterName);
|
||||
}
|
||||
|
||||
public function testApply2()
|
||||
{
|
||||
$filterName = 'test';
|
||||
|
||||
$this->filterFactory
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with($this->entityType, $filterName)
|
||||
->willReturn(false);
|
||||
|
||||
$this->filterFactory
|
||||
->expects($this->never())
|
||||
->method('create');
|
||||
|
||||
$this->expectException(BadRequest::class);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $filterName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
|
||||
|
||||
use Espo\Core\Select\SearchParams;
|
||||
use Espo\Core\Select\Select\Applier as SelectApplier;
|
||||
use Espo\Core\Select\Select\MetadataProvider;
|
||||
use Espo\Core\Utils\FieldUtil;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SelectApplierTest extends TestCase
|
||||
{
|
||||
private $metadataProvider;
|
||||
private $queryBuilder;
|
||||
private $applier;
|
||||
private $entityType;
|
||||
private $fieldUtil;
|
||||
private $searchParams;
|
||||
private $user;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
$this->searchParams = $this->createMock(SearchParams::class);
|
||||
$this->fieldUtil = $this->createMock(FieldUtil::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->applier = new SelectApplier(
|
||||
$this->entityType,
|
||||
$this->user,
|
||||
$this->fieldUtil,
|
||||
$this->metadataProvider
|
||||
);
|
||||
}
|
||||
|
||||
public function testApply1()
|
||||
{
|
||||
$this->initTestApply();
|
||||
}
|
||||
|
||||
public function testApplyPortal()
|
||||
{
|
||||
$this->initTestApply(true);
|
||||
}
|
||||
|
||||
protected function initTestApply(bool $isPortal = false)
|
||||
{
|
||||
$select = ['testSelect', 'testNotExisting', 'testText'];
|
||||
|
||||
$orderBy = 'testOrder';
|
||||
|
||||
$aclAttributeList = ['testAcl'];
|
||||
|
||||
$aclPortalAttributeList = ['testAclPortal'];
|
||||
|
||||
$dependencyMap = [
|
||||
'testSelect' => [
|
||||
'testDependency',
|
||||
],
|
||||
];
|
||||
|
||||
$aclAttribute = $aclAttributeList[0];
|
||||
|
||||
if ($isPortal) {
|
||||
$aclAttribute = $aclPortalAttributeList[0];
|
||||
}
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('isPortal')
|
||||
->willReturn($isPortal);
|
||||
|
||||
$this->searchParams
|
||||
->expects($this->any())
|
||||
->method('getMaxTextAttributeLength')
|
||||
->willReturn(100);
|
||||
|
||||
$this->searchParams
|
||||
->expects($this->any())
|
||||
->method('getSelect')
|
||||
->willReturn($select);
|
||||
|
||||
$this->searchParams
|
||||
->expects($this->any())
|
||||
->method('getOrderBy')
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getAclAttributeList')
|
||||
->willReturn($aclAttributeList);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getAclPortalAttributeList')
|
||||
->willReturn($aclPortalAttributeList);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getSelectAttributesDependencyMap')
|
||||
->with($this->entityType)
|
||||
->willReturn($dependencyMap);
|
||||
|
||||
$this->fieldUtil
|
||||
->expects($this->once())
|
||||
->method('getAttributeList')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn([$orderBy]);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('hasAttribute')
|
||||
->willReturnMap(
|
||||
[
|
||||
[$this->entityType, 'id', true],
|
||||
[$this->entityType, 'testSelect', true],
|
||||
[$this->entityType, 'testNotExisting', false],
|
||||
[$this->entityType, 'testOrder', true],
|
||||
[$this->entityType, 'testAcl', true],
|
||||
[$this->entityType, 'testAclPortal', true],
|
||||
[$this->entityType, 'testDependency', true],
|
||||
[$this->entityType, 'testText', true],
|
||||
]
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('isAttributeNotStorable')
|
||||
->willReturn(false);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getAttributeType')
|
||||
->willReturnMap(
|
||||
[
|
||||
[$this->entityType, 'id', Entity::ID],
|
||||
[$this->entityType, 'testSelect', Entity::VARCHAR],
|
||||
[$this->entityType, 'testOrder', Entity::VARCHAR],
|
||||
[$this->entityType, 'testAcl', Entity::VARCHAR],
|
||||
[$this->entityType, 'testAclPortal', Entity::VARCHAR],
|
||||
[$this->entityType, 'testDependency', Entity::VARCHAR],
|
||||
[$this->entityType, 'testText', Entity::TEXT],
|
||||
]
|
||||
);
|
||||
|
||||
$expected = [
|
||||
'id',
|
||||
$aclAttribute,
|
||||
'testSelect',
|
||||
['LEFT:(testText, 100)', 'testText'],
|
||||
'testOrder',
|
||||
'testDependency',
|
||||
];
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('select')
|
||||
->with($expected);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->searchParams);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
|
||||
|
||||
use Espo\Core\Select\Text\Applier as TextFilterApplier;
|
||||
use Espo\Core\Select\Text\ConfigProvider;
|
||||
use Espo\Core\Select\Text\DefaultFilter;
|
||||
use Espo\Core\Select\Text\FilterFactory;
|
||||
use Espo\Core\Select\Text\FilterParams;
|
||||
use Espo\Core\Select\Text\FullTextSearch\Data as FullTextSearchData;
|
||||
use Espo\Core\Select\Text\FullTextSearch\DataComposer\Params as FullTextSearchDataComposerParams;
|
||||
use Espo\Core\Select\Text\FullTextSearch\DataComposerFactory as FullTextSearchDataComposerFactory;
|
||||
use Espo\Core\Select\Text\FullTextSearch\DefaultDataComposer as FullTextSearchDataComposer;
|
||||
use Espo\Core\Select\Text\MetadataProvider;
|
||||
use Espo\Core\Utils\Config;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\Query\Part\Expression as Expr;
|
||||
use Espo\ORM\Query\Part\Where\OrGroup;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class TextFilterApplierTest extends TestCase
|
||||
{
|
||||
private $metadataProvider;
|
||||
private $queryBuilder;
|
||||
private $filterParams;
|
||||
private $config;
|
||||
private $fullTextSearchDataComposerFactory;
|
||||
private $filterFactory;
|
||||
private $applier;
|
||||
private $entityType;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$user = $this->createMock(User::class);
|
||||
$this->metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
$this->filterParams = $this->createMock(FilterParams::class);
|
||||
$this->config = $this->createMock(Config::class);
|
||||
$this->fullTextSearchDataComposerFactory = $this->createMock(FullTextSearchDataComposerFactory::class);
|
||||
$this->filterFactory = $this->createMock(FilterFactory::class);
|
||||
|
||||
$configProvider = $this->createMock(ConfigProvider::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->applier = new TextFilterApplier(
|
||||
$this->entityType,
|
||||
$user,
|
||||
$this->metadataProvider,
|
||||
$this->fullTextSearchDataComposerFactory,
|
||||
$this->filterFactory,
|
||||
$configProvider
|
||||
);
|
||||
}
|
||||
|
||||
public function testApply1()
|
||||
{
|
||||
$this->initTest(false);
|
||||
}
|
||||
|
||||
public function testApply2()
|
||||
{
|
||||
$this->initTest(true);
|
||||
}
|
||||
|
||||
public function testApply3()
|
||||
{
|
||||
$this->initTest(false, '1000');
|
||||
}
|
||||
|
||||
protected function initTest(bool $noFullTextSearch = false, ?string $filter = null)
|
||||
{
|
||||
$filter = $filter ?? 'test';
|
||||
|
||||
$filterParams = $this->createMock(FilterParams::class);
|
||||
|
||||
$filterParams
|
||||
->expects($this->any())
|
||||
->method('noFullTextSearch')
|
||||
->willReturn($noFullTextSearch);
|
||||
|
||||
$this->config
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
['textFilterUseContainsForVarchar', false],
|
||||
['textFilterContainsMinLength', 4],
|
||||
]
|
||||
|
||||
);
|
||||
|
||||
$configProvider = new ConfigProvider($this->config);
|
||||
|
||||
$defaultFilter = new DefaultFilter(
|
||||
$this->entityType,
|
||||
$this->metadataProvider,
|
||||
$configProvider
|
||||
);
|
||||
|
||||
$this->filterFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->willReturn(
|
||||
$defaultFilter
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getFullTextSearchOrderType')
|
||||
->with($this->entityType)
|
||||
->willReturn(null);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getAttributeType')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
[$this->entityType, 'fieldVarchar', Entity::VARCHAR],
|
||||
[$this->entityType, 'fieldText', Entity::TEXT],
|
||||
[$this->entityType, 'fieldFullText', Entity::TEXT],
|
||||
[$this->entityType, 'fieldInt', Entity::INT],
|
||||
[$this->entityType, 'fieldForeign', Entity::FOREIGN],
|
||||
['ForeignEntityType', 'field', Entity::VARCHAR],
|
||||
]
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getAttributeRelationParam')
|
||||
->with($this->entityType, 'fieldForeign')
|
||||
->willReturn('link1');
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getRelationType')
|
||||
->with($this->entityType, 'link2')
|
||||
->willReturn(Entity::HAS_MANY);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getRelationEntityType')
|
||||
->with($this->entityType, 'link2')
|
||||
->willReturn('ForeignEntityType');
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getTextFilterAttributeList')
|
||||
->with($this->entityType)
|
||||
->willReturn(
|
||||
['fieldVarchar', 'fieldText', 'fieldFullText', 'fieldInt', 'fieldForeign', 'link2.field']
|
||||
);
|
||||
|
||||
if (!$noFullTextSearch) {
|
||||
$this->initFullTextSearchData($filter, ['fieldFullText'], 'TEST:(test)');
|
||||
}
|
||||
|
||||
$expectedWhere = [
|
||||
['fieldVarchar*' => $filter . '%'],
|
||||
['fieldText*' => '%' . $filter . '%']
|
||||
];
|
||||
|
||||
if (is_numeric($filter)) {
|
||||
$expectedWhere[] = ['fieldInt=' => intval($filter)];
|
||||
}
|
||||
|
||||
if ($noFullTextSearch) {
|
||||
$expectedWhere[] = ['fieldFullText*' => '%' . $filter . '%'];
|
||||
}
|
||||
|
||||
$expectedWhere[] = ['fieldForeign*' => $filter . '%'];
|
||||
$expectedWhere[] = ['link2.field*' => $filter . '%'];
|
||||
|
||||
if (!$noFullTextSearch) {
|
||||
$expectedWhere[] = ['NOT_EQUAL:(TEST:(test), 0):' => null];
|
||||
}
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('where')
|
||||
->with(OrGroup::fromRaw($expectedWhere));
|
||||
|
||||
$c = $this->exactly(2);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($c)
|
||||
->method('leftJoin')
|
||||
->willReturnCallback(function ($link) use ($c) {
|
||||
if ($c->numberOfInvocations() === 1) {
|
||||
$this->assertEquals('link1', $link);
|
||||
}
|
||||
|
||||
if ($c->numberOfInvocations() === 2) {
|
||||
$this->assertEquals('link2', $link);
|
||||
}
|
||||
|
||||
return $this->queryBuilder;
|
||||
});
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('distinct');
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $filter, $this->filterParams);
|
||||
}
|
||||
|
||||
protected function initFullTextSearchData(string $filter, array $fieldList, string $expression)
|
||||
{
|
||||
$fullTextSearchData = $this->createMock(FullTextSearchData::class);
|
||||
|
||||
$fullTextSearchDataComposer = $this->createMock(FullTextSearchDataComposer::class);
|
||||
|
||||
$fullTextSearchDataComposerParams = FullTextSearchDataComposerParams::create();
|
||||
|
||||
$this->fullTextSearchDataComposerFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType)
|
||||
->willReturn($fullTextSearchDataComposer);
|
||||
|
||||
$fullTextSearchData
|
||||
->expects($this->any())
|
||||
->method('getFieldList')
|
||||
->willReturn($fieldList);
|
||||
|
||||
$fullTextSearchData
|
||||
->expects($this->any())
|
||||
->method('getExpression')
|
||||
->willReturn(Expr::create($expression));
|
||||
|
||||
$fullTextSearchDataComposer
|
||||
->expects($this->any())
|
||||
->method('compose')
|
||||
->with($filter, $fullTextSearchDataComposerParams)
|
||||
->willReturn($fullTextSearchData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
|
||||
|
||||
use Espo\Core\Select\Where\Applier as WhereApplier;
|
||||
use Espo\Core\Select\Where\Checker;
|
||||
use Espo\Core\Select\Where\CheckerFactory;
|
||||
use Espo\Core\Select\Where\Converter;
|
||||
use Espo\Core\Select\Where\ConverterFactory;
|
||||
use Espo\Core\Select\Where\Item as WhereItem;
|
||||
use Espo\Core\Select\Where\Params;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class WhereApplierTest extends TestCase
|
||||
{
|
||||
private $user;
|
||||
private $queryBuilder;
|
||||
private $whereItem;
|
||||
private $converterFactory;
|
||||
private $converter;
|
||||
private $checkerFactory;
|
||||
private $checker;
|
||||
private $params;
|
||||
private $entityType;
|
||||
private $applier;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
$this->whereItem = $this->createMock(WhereItem::class);
|
||||
$this->converterFactory = $this->createMock(ConverterFactory::class);
|
||||
$this->converter = $this->createMock(Converter::class);
|
||||
$this->checkerFactory = $this->createMock(CheckerFactory::class);
|
||||
$this->checker = $this->createMock(Checker::class);
|
||||
$this->params = $this->createMock(Params::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->applier = new WhereApplier(
|
||||
$this->entityType,
|
||||
$this->user,
|
||||
$this->converterFactory,
|
||||
$this->checkerFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function testApply1()
|
||||
{
|
||||
$this->checker
|
||||
->expects($this->once())
|
||||
->method('check')
|
||||
->with($this->whereItem, $this->params);
|
||||
|
||||
$this->checkerFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $this->user)
|
||||
->willReturn($this->checker);
|
||||
|
||||
$this->converter
|
||||
->expects($this->once())
|
||||
->method('convert')
|
||||
->with($this->queryBuilder, $this->whereItem);
|
||||
|
||||
$this->converterFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $this->user)
|
||||
->willReturn($this->converter);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->whereItem, $this->params);
|
||||
}
|
||||
|
||||
public function testApply2()
|
||||
{
|
||||
$this->checker
|
||||
->expects($this->once())
|
||||
->method('check')
|
||||
->with($this->whereItem, $this->params);
|
||||
|
||||
$this->checkerFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $this->user)
|
||||
->willReturn($this->checker);
|
||||
|
||||
$this->converter
|
||||
->expects($this->once())
|
||||
->method('convert')
|
||||
->with($this->queryBuilder, $this->whereItem);
|
||||
|
||||
$this->converterFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $this->user)
|
||||
->willReturn($this->converter);
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->whereItem, $this->params);
|
||||
}
|
||||
}
|
||||
171
tests/unit/Espo/Core/Select/Applier/FactoryTest.php
Normal file
171
tests/unit/Espo/Core/Select/Applier/FactoryTest.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Applier;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\AclManager;
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\AccessControl\Applier as AccessControlFilterApplier;
|
||||
use Espo\Core\Select\Applier\Appliers\Additional as AdditionalApplier;
|
||||
use Espo\Core\Select\Applier\Appliers\Limit as LimitApplier;
|
||||
use Espo\Core\Select\Applier\Factory as ApplierFactory;
|
||||
use Espo\Core\Select\Bool\Applier as BoolFilterListApplier;
|
||||
use Espo\Core\Select\Order\Applier as OrderApplier;
|
||||
use Espo\Core\Select\Primary\Applier as PrimaryFilterApplier;
|
||||
use Espo\Core\Select\Select\Applier as SelectApplier;
|
||||
use Espo\Core\Select\Text\Applier as TextFilterApplier;
|
||||
use Espo\Core\Select\Where\Applier as WhereApplier;
|
||||
|
||||
use Espo\Core\Utils\Acl\UserAclManagerProvider;
|
||||
use Espo\Entities\User;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FactoryTest extends TestCase
|
||||
{
|
||||
private $aclManager;
|
||||
private $acl;
|
||||
private $injectableFactory;
|
||||
private $user;
|
||||
private $factory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$userAclManagerProvider = $this->createMock(UserAclManagerProvider::class);
|
||||
|
||||
$this->aclManager = $this->createMock(AclManager::class);
|
||||
|
||||
$userAclManagerProvider
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturn($this->aclManager);
|
||||
|
||||
$this->factory = new ApplierFactory(
|
||||
$this->injectableFactory,
|
||||
$userAclManagerProvider,
|
||||
);
|
||||
|
||||
$this->acl = $this->createMock(Acl::class);
|
||||
|
||||
$this->aclManager
|
||||
->expects($this->any())
|
||||
->method('createUserAcl')
|
||||
->willReturn($this->acl);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(SelectApplier::class, ApplierFactory::SELECT, 'createSelect');
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest(
|
||||
BoolFilterListApplier::class, ApplierFactory::BOOL_FILTER_LIST, 'createBoolFilterList');
|
||||
}
|
||||
|
||||
public function testCreate3()
|
||||
{
|
||||
$this->prepareFactoryTest(TextFilterApplier::class, ApplierFactory::TEXT_FILTER, 'createTextFilter');
|
||||
}
|
||||
|
||||
public function testCreate4()
|
||||
{
|
||||
$this->prepareFactoryTest(WhereApplier::class, ApplierFactory::WHERE, 'createWhere');
|
||||
}
|
||||
|
||||
public function testCreate5()
|
||||
{
|
||||
$this->prepareFactoryTest(OrderApplier::class, ApplierFactory::ORDER, 'createOrder');
|
||||
}
|
||||
|
||||
public function testCreate6()
|
||||
{
|
||||
$this->prepareFactoryTest(LimitApplier::class, ApplierFactory::LIMIT, 'createLimit');
|
||||
}
|
||||
|
||||
public function testCreate7()
|
||||
{
|
||||
$this->prepareFactoryTest(AdditionalApplier::class, ApplierFactory::ADDITIONAL, 'createAdditional');
|
||||
}
|
||||
|
||||
public function testCreate8()
|
||||
{
|
||||
$this->prepareFactoryTest(
|
||||
PrimaryFilterApplier::class, ApplierFactory::PRIMARY_FILTER, 'createPrimaryFilter');
|
||||
}
|
||||
|
||||
public function testCreate9()
|
||||
{
|
||||
$this->prepareFactoryTest(
|
||||
AccessControlFilterApplier::class, ApplierFactory::ACCESS_CONTROL_FILTER, 'createAccessControlFilter');
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(string $defaultClassName, string $type, string $method)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$applierClassName = $className ?? $defaultClassName;
|
||||
|
||||
$applier = $this->createMock($defaultClassName);
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $this->user)
|
||||
->bindInstance(AclManager::class, $this->aclManager)
|
||||
->bindInstance(Acl::class, $this->acl)
|
||||
->for($applierClassName)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bindingContainer = new BindingContainer($bindingData);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWithBinding')
|
||||
->with($applierClassName, $bindingContainer)
|
||||
->willReturn($applier);
|
||||
|
||||
$resultApplier = $this->factory->$method(
|
||||
$entityType,
|
||||
$this->user,
|
||||
$type
|
||||
);
|
||||
|
||||
$this->assertEquals($applier, $resultApplier);
|
||||
}
|
||||
}
|
||||
145
tests/unit/Espo/Core/Select/Bool/FilterFactoryTest.php
Normal file
145
tests/unit/Espo/Core/Select/Bool/FilterFactoryTest.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Bool;
|
||||
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\Bool\FilterFactory as BoolFilterFactory;
|
||||
use Espo\Core\Select\Bool\Filters\Followed;
|
||||
use Espo\Core\Select\Helpers\FieldHelper;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\User;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FilterFactoryTest extends TestCase
|
||||
{
|
||||
private $injectableFactory;
|
||||
private $metadata;
|
||||
private $user;
|
||||
private $factory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$this->factory = new BoolFilterFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(null, Followed::class, 'followed');
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest('SomeClass', Followed::class, 'followed');
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className, string $defaultClassName, string $name)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'boolFilterClassNameMap', $name], null, $className],
|
||||
]);
|
||||
|
||||
$className = $className ?? $defaultClassName;
|
||||
|
||||
$object = $this->createMock($defaultClassName);
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $this->user)
|
||||
->for($className)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$binder
|
||||
->for(FieldHelper::class)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bindingContainer = new BindingContainer($bindingData);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWithBinding')
|
||||
->with($className, $bindingContainer)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create(
|
||||
$entityType,
|
||||
$this->user,
|
||||
$name
|
||||
);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->factory->has($entityType, $name)
|
||||
);
|
||||
|
||||
$this->metadata
|
||||
->expects(self::any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[
|
||||
[
|
||||
'selectDefs',
|
||||
$entityType,
|
||||
'boolFilterClassNameMap',
|
||||
'badName',
|
||||
],
|
||||
null,
|
||||
null
|
||||
],
|
||||
[
|
||||
['app', 'select', 'boolFilterClassNameMap', 'badName'],
|
||||
null,
|
||||
null
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->factory->has($entityType, 'badName')
|
||||
);
|
||||
}
|
||||
}
|
||||
118
tests/unit/Espo/Core/Select/Bool/FiltersTest.php
Normal file
118
tests/unit/Espo/Core/Select/Bool/FiltersTest.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Bool;
|
||||
|
||||
use Espo\Core\Select\Bool\Filters\OnlyMy;
|
||||
use Espo\Core\Select\Bool\Filters\Shared;
|
||||
use Espo\Core\Select\Helpers\FieldHelper;
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Defs;
|
||||
use Espo\ORM\Defs\EntityDefs;
|
||||
use Espo\ORM\Defs\RelationDefs;
|
||||
use Espo\ORM\Query\Part\Where\OrGroupBuilder;
|
||||
use Espo\ORM\Query\Select;
|
||||
use Espo\ORM\Query\SelectBuilder;
|
||||
use Espo\ORM\Type\RelationType;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FiltersTest extends TestCase
|
||||
{
|
||||
public function testOnlyMyUsesMiddleConditions(): void
|
||||
{
|
||||
$user = $this->createMock(User::class);
|
||||
$user->method('getId')->willReturn('user-id');
|
||||
$user->method('isPortal')->willReturn(false);
|
||||
|
||||
$fieldHelper = $this->createMock(FieldHelper::class);
|
||||
$fieldHelper->method('hasAssignedUsersField')->willReturn(true);
|
||||
|
||||
$filter = new OnlyMy('Test', $user, $fieldHelper, $this->createDefs('assignedUsers', 'entityUser'));
|
||||
|
||||
$joinConditions = $this->applyAndGetJoinConditions($filter);
|
||||
|
||||
$this->assertEquals('Test', $joinConditions['assignedUsersMiddle.entityType'] ?? null);
|
||||
}
|
||||
|
||||
public function testSharedUsesMiddleConditions(): void
|
||||
{
|
||||
$user = $this->createMock(User::class);
|
||||
$user->method('getId')->willReturn('user-id');
|
||||
|
||||
$fieldHelper = $this->createMock(FieldHelper::class);
|
||||
$fieldHelper->method('hasCollaboratorsField')->willReturn(true);
|
||||
|
||||
$filter = new Shared('Test', $user, $fieldHelper, $this->createDefs('collaborators', 'entityCollaborator'));
|
||||
|
||||
$joinConditions = $this->applyAndGetJoinConditions($filter);
|
||||
|
||||
$this->assertEquals('Test', $joinConditions['collaboratorsMiddle.entityType'] ?? null);
|
||||
}
|
||||
|
||||
private function createDefs(string $link, string $relationName): Defs
|
||||
{
|
||||
$relationDefs = RelationDefs::fromRaw([
|
||||
'type' => RelationType::MANY_MANY,
|
||||
'entity' => User::ENTITY_TYPE,
|
||||
'relationName' => $relationName,
|
||||
'midKeys' => ['entityId', 'userId'],
|
||||
'conditions' => ['entityType' => 'Test'],
|
||||
], $link);
|
||||
|
||||
$entityDefs = $this->createMock(EntityDefs::class);
|
||||
$entityDefs->method('getRelation')->with($link)->willReturn($relationDefs);
|
||||
|
||||
$defs = $this->createMock(Defs::class);
|
||||
$defs->method('getEntity')->with('Test')->willReturn($entityDefs);
|
||||
|
||||
return $defs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function applyAndGetJoinConditions(OnlyMy|Shared $filter): array
|
||||
{
|
||||
$orGroupBuilder = new OrGroupBuilder();
|
||||
|
||||
$filter->apply(SelectBuilder::create()->from('Test'), $orGroupBuilder);
|
||||
|
||||
$rawValue = $orGroupBuilder->build()->getRawValue();
|
||||
|
||||
$subQuery = $rawValue['id=s'] ?? null;
|
||||
|
||||
$this->assertInstanceOf(Select::class, $subQuery);
|
||||
|
||||
$joins = $subQuery->getRaw()['joins'] ?? [];
|
||||
|
||||
$this->assertCount(1, $joins);
|
||||
|
||||
return $joins[0][2];
|
||||
}
|
||||
}
|
||||
162
tests/unit/Espo/Core/Select/Order/ItemConverterFactoryTest.php
Normal file
162
tests/unit/Espo/Core/Select/Order/ItemConverterFactoryTest.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Order;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\Order\ItemConverter;
|
||||
use Espo\Core\Select\Order\ItemConverterFactory;
|
||||
use Espo\Core\Select\Order\ItemConverters\EnumType;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
|
||||
use Espo\Core\Binding\BindingContainerBuilder;
|
||||
use Espo\Core\Binding\ContextualBinder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ItemConverterFactoryTest extends TestCase
|
||||
{
|
||||
private $injectableFactory;
|
||||
private $metadata;
|
||||
private $user;
|
||||
private $factory;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$this->factory = new ItemConverterFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata,
|
||||
$this->user
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(null, EnumType::class);
|
||||
$this->prepareFactoryTest(null, EnumType::class, true);
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest(EnumType::class, null);
|
||||
$this->prepareFactoryTest(EnumType::class, null, true);
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className1, ?string $className2, bool $testHas = false)
|
||||
{
|
||||
$defaultClassName = ItemConverter::class;
|
||||
|
||||
$entityType = 'Test';
|
||||
|
||||
$field = 'name';
|
||||
|
||||
$type = 'varchar';
|
||||
|
||||
$object = $this->createMock($defaultClassName);
|
||||
|
||||
$className = $className1 ?? $className2 ?? null;
|
||||
|
||||
if (!$className1) {
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'orderItemConverterClassNameMap', $field], null, $className1],
|
||||
[['entityDefs', $entityType, 'fields', $field, 'type'], null, $type],
|
||||
[['app', 'select', 'orderItemConverterClassNameMap', $type], null, $className2],
|
||||
]);
|
||||
} else {
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'orderItemConverterClassNameMap', $field], null, $className1],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($testHas) {
|
||||
$this->assertTrue(
|
||||
$this->factory->has($entityType, $field)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$object = $this->createMock($className);
|
||||
|
||||
$container = BindingContainerBuilder::create()
|
||||
->bindInstance(User::class, $this->user)
|
||||
->inContext($className, function (ContextualBinder $binder) use ($entityType) {
|
||||
$binder->bindValue('$entityType', $entityType);
|
||||
})
|
||||
->build();
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWithBinding')
|
||||
->with(
|
||||
$className,
|
||||
$container
|
||||
)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create(
|
||||
$entityType,
|
||||
$field
|
||||
);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
}
|
||||
|
||||
public function testHasFalse()
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$field = 'name';
|
||||
|
||||
$type = 'varchar';
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'orderItemConverterClassNameMap', 'badName'], null, null],
|
||||
[['entityDefs', $entityType, 'fields', 'badName', 'type'], null, $type],
|
||||
[['app', 'select', 'orderItemConverterClassNameMap', $type], null, null],
|
||||
]);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->factory->has($entityType, 'badName')
|
||||
);
|
||||
}
|
||||
}
|
||||
51
tests/unit/Espo/Core/Select/Order/ItemTest.php
Normal file
51
tests/unit/Espo/Core/Select/Order/ItemTest.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Order;
|
||||
|
||||
use Espo\Core\Select\Order\Item;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class ItemTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testCreate1()
|
||||
{
|
||||
$item = Item::create('test', 'DESC');
|
||||
|
||||
$this->assertEquals('DESC', $item->getOrder());
|
||||
$this->assertEquals('test', $item->getOrderBy());
|
||||
}
|
||||
public function testNonExistingParam()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
Item::create('test', 'test');
|
||||
}
|
||||
}
|
||||
95
tests/unit/Espo/Core/Select/Order/ParamsTest.php
Normal file
95
tests/unit/Espo/Core/Select/Order/ParamsTest.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Order;
|
||||
|
||||
use Espo\Core\{
|
||||
Select\Order\Params,
|
||||
};
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class ParamsTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function setUp() : void
|
||||
{
|
||||
}
|
||||
|
||||
public function testFromArray()
|
||||
{
|
||||
$item = Params::fromAssoc([
|
||||
'order' => 'DESC',
|
||||
'orderBy' => 'test',
|
||||
//'forbidComplexExpressions' => true,
|
||||
'forceDefault' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals('DESC', $item->getOrder());
|
||||
$this->assertEquals('test', $item->getOrderBy());
|
||||
//$this->assertTrue($item->forbidComplexExpressions());
|
||||
$this->assertTrue($item->forceDefault());
|
||||
|
||||
$item = Params::fromAssoc([
|
||||
//'forbidComplexExpressions' => false,
|
||||
'forceDefault' => false,
|
||||
]);
|
||||
|
||||
//$this->assertFalse($item->forbidComplexExpressions());
|
||||
$this->assertFalse($item->forceDefault());
|
||||
}
|
||||
|
||||
public function testEmpty()
|
||||
{
|
||||
$item = Params::fromAssoc([
|
||||
]);
|
||||
|
||||
$this->assertEquals(null, $item->getOrder());
|
||||
$this->assertEquals(null, $item->getOrderBy());
|
||||
//$this->assertEquals(false, $item->forbidComplexExpressions());
|
||||
$this->assertEquals(false, $item->forceDefault());
|
||||
}
|
||||
|
||||
public function testBadOrder()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = Params::fromAssoc([
|
||||
'order' => 'd',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testNonExistingParam()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = Params::fromAssoc([
|
||||
'bad' => 'd',
|
||||
]);
|
||||
}
|
||||
}
|
||||
136
tests/unit/Espo/Core/Select/Primary/FilterFactoryTest.php
Normal file
136
tests/unit/Espo/Core/Select/Primary/FilterFactoryTest.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Primary;
|
||||
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\Helpers\FieldHelper;
|
||||
use Espo\Core\Select\Primary\FilterFactory as PrimaryFilterFactory;
|
||||
use Espo\Core\Select\Primary\Filters\Followed;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\User;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FilterFactoryTest extends TestCase
|
||||
{
|
||||
private $injectableFactory;
|
||||
private $metadata;
|
||||
private $user;
|
||||
private $factory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$this->factory = new PrimaryFilterFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(null, Followed::class, 'followed');
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest('SomeClass', Followed::class, 'followed');
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className, string $defaultClassName, string $name)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'primaryFilterClassNameMap', $name], null, $className],
|
||||
]);
|
||||
|
||||
$className = $className ?? $defaultClassName;
|
||||
|
||||
$object = $this->createMock($defaultClassName);
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $this->user)
|
||||
->for($className)
|
||||
->bindValue('$entityType', $entityType)
|
||||
->bindValue('$name', $name);
|
||||
|
||||
$binder
|
||||
->for(FieldHelper::class)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bindingContainer = new BindingContainer($bindingData);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWithBinding')
|
||||
->with($className, $bindingContainer)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create(
|
||||
$entityType,
|
||||
$this->user,
|
||||
$name
|
||||
);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->factory->has($entityType, $name)
|
||||
);
|
||||
|
||||
$this->metadata
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with([
|
||||
'selectDefs',
|
||||
$entityType,
|
||||
'primaryFilterClassNameMap',
|
||||
'badName',
|
||||
])
|
||||
->willReturn(null);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->factory->has($entityType, 'badName')
|
||||
);
|
||||
}
|
||||
}
|
||||
407
tests/unit/Espo/Core/Select/SearchParamsTest.php
Normal file
407
tests/unit/Espo/Core/Select/SearchParamsTest.php
Normal file
@@ -0,0 +1,407 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select;
|
||||
|
||||
use Espo\Core\{
|
||||
Select\SearchParams,
|
||||
Select\Where\Item as WhereItem,
|
||||
};
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class SearchParamsTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testFromRaw1()
|
||||
{
|
||||
$raw = [
|
||||
'select' => ['id', 'name'],
|
||||
'offset' => 0,
|
||||
'maxSize' => 10,
|
||||
'order' => 'desc',
|
||||
'orderBy' => 'testOrderBy',
|
||||
'boolFilterList' => ['test1', 'test2'],
|
||||
'textFilter' => 'test',
|
||||
'primaryFilter' => 'testPrimary',
|
||||
'where' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test',
|
||||
'value' => 'Test',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$params = SearchParams::fromRaw($raw);
|
||||
|
||||
$this->assertEquals(['id', 'name'], $params->getSelect());
|
||||
$this->assertEquals(0, $params->getOffset());
|
||||
$this->assertEquals(10, $params->getMaxSize());
|
||||
$this->assertEquals('DESC', $params->getOrder());
|
||||
$this->assertEquals('testOrderBy', $params->getOrderBy());
|
||||
$this->assertEquals(['test1', 'test2'], $params->getBoolFilterList());
|
||||
$this->assertEquals('test', $params->getTextFilter());
|
||||
$this->assertEquals('testPrimary', $params->getPrimaryFilter());
|
||||
$this->assertEquals($raw['where'], $params->getWhere()->getRaw()['value']);
|
||||
}
|
||||
|
||||
public function testFromRawEmpty()
|
||||
{
|
||||
$params = SearchParams::fromRaw([]);
|
||||
|
||||
$this->assertEquals(null, $params->getSelect());
|
||||
$this->assertEquals(null, $params->getOffset());
|
||||
$this->assertEquals(null, $params->getMaxSize());
|
||||
$this->assertEquals(null, $params->getOrder());
|
||||
$this->assertEquals(null, $params->getOrderBy());
|
||||
$this->assertEquals(null, $params->getTextFilter());
|
||||
$this->assertEquals(null, $params->getPrimaryFilter());
|
||||
$this->assertEquals(null, $params->getWhere());
|
||||
}
|
||||
|
||||
public function testQ()
|
||||
{
|
||||
$params = SearchParams::fromRaw([
|
||||
'q' => 'test',
|
||||
]);
|
||||
|
||||
$this->assertEquals('test', $params->getTextFilter());
|
||||
}
|
||||
|
||||
public function testOrder()
|
||||
{
|
||||
$raw = [
|
||||
|
||||
'order' => 'asc',
|
||||
];
|
||||
|
||||
$params = SearchParams::fromRaw($raw);
|
||||
|
||||
$this->assertEquals('ASC', $params->getOrder());
|
||||
}
|
||||
|
||||
public function testMaxTextAttributeLength()
|
||||
{
|
||||
$raw = [
|
||||
'maxTextAttributeLength' => 1000,
|
||||
];
|
||||
|
||||
$params = SearchParams::fromRaw($raw);
|
||||
|
||||
$this->assertEquals(1000, $params->getMaxTextAttributeLength());
|
||||
}
|
||||
|
||||
public function testAdjust()
|
||||
{
|
||||
$raw = [
|
||||
'where' => [
|
||||
[
|
||||
'type' => 'primary',
|
||||
'value' => 'testPrimary',
|
||||
],
|
||||
[
|
||||
'type' => 'textFilter',
|
||||
'value' => 'testText',
|
||||
],
|
||||
[
|
||||
'type' => 'bool',
|
||||
'value' => ['test'],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$params = SearchParams::fromRaw($raw);
|
||||
|
||||
$this->assertEquals('testPrimary', $params->getPrimaryFilter());
|
||||
$this->assertEquals('testText', $params->getTextFilter());
|
||||
$this->assertEquals(['test'], $params->getBoolFilterList());
|
||||
}
|
||||
|
||||
public function testBadSelect1()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'select' => 'id,name',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadSelect2()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'select' => [1],
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadOffset()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'offset' => 'hello',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadBoolFilterList1()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'boolFilterList' => 'test',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadBoolFilterList2()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'boolFilterList' => [1],
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadTextFilter()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'textFilter' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadPrimaryFilter()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'primaryFilter' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadWhere()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'where' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadOrder1()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'order' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testBadOrder2()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = SearchParams::fromRaw([
|
||||
'order' => 'd',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testMerge1()
|
||||
{
|
||||
$params1 = SearchParams::fromRaw([
|
||||
'boolFilterList' => ['f1', 'f2'],
|
||||
'textFilter' => 't1',
|
||||
'where' => [
|
||||
[
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 't',
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$params2 = SearchParams::fromRaw([
|
||||
'boolFilterList' => ['f2', 'f3'],
|
||||
'textFilter' => 't2',
|
||||
'where' => [
|
||||
[
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 't2',
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$params = SearchParams::merge($params1, $params2);
|
||||
|
||||
$actual = $params->getRaw();
|
||||
|
||||
$expected = [
|
||||
'boolFilterList' => ['f2', 'f3', 'f1'],
|
||||
'textFilter' => 't1',
|
||||
'where' => [
|
||||
[
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 't2',
|
||||
],
|
||||
[
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 't',
|
||||
],
|
||||
],
|
||||
'select' => null,
|
||||
'orderBy' => null,
|
||||
'order' => null,
|
||||
'offset' => null,
|
||||
'maxSize' => null,
|
||||
'primaryFilter' => null,
|
||||
'maxTextAttributeLength' => null,
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testCloning(): void
|
||||
{
|
||||
$rawWhere = [
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 't',
|
||||
];
|
||||
|
||||
$params = SearchParams
|
||||
::create()
|
||||
->withBoolFilterList(['a'])
|
||||
->withMaxSize(10)
|
||||
->withOffset(0)
|
||||
->withMaxTextAttributeLength(100)
|
||||
->withOrder('DESC')
|
||||
->withOrderBy('name')
|
||||
->withPrimaryFilter('test')
|
||||
->withSelect(['name'])
|
||||
->withTextFilter('test*')
|
||||
->withWhere(WhereItem::fromRaw($rawWhere));
|
||||
|
||||
$this->assertEquals(['a'], $params->getBoolFilterList());
|
||||
$this->assertEquals(10, $params->getMaxSize());
|
||||
$this->assertEquals(0, $params->getOffset());
|
||||
$this->assertEquals(100, $params->getMaxTextAttributeLength());
|
||||
$this->assertEquals('DESC', $params->getOrder());
|
||||
$this->assertEquals('name', $params->getOrderBy());
|
||||
$this->assertEquals('test', $params->getPrimaryFilter());
|
||||
$this->assertEquals(['name'], $params->getSelect());
|
||||
$this->assertEquals('test*', $params->getTextFilter());
|
||||
$this->assertEquals('isTrue', $params->getWhere()->getRaw()['value'][0]['type']);
|
||||
}
|
||||
|
||||
public function testWithWhereAdded1(): void
|
||||
{
|
||||
$params = SearchParams
|
||||
::create()
|
||||
->withWhere(
|
||||
WhereItem::fromRaw([
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 'a1',
|
||||
])
|
||||
)
|
||||
->withWhereAdded(
|
||||
WhereItem::fromRaw([
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 'a2',
|
||||
])
|
||||
);
|
||||
|
||||
$where = $params->getWhere();
|
||||
|
||||
$this->assertEquals(WhereItem\Type::AND, $where->getType());
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'type' => WhereItem\Type::AND,
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 'a1',
|
||||
'value' => null,
|
||||
],
|
||||
[
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 'a2',
|
||||
'value' => null,
|
||||
],
|
||||
],
|
||||
],
|
||||
$where->getRaw()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWithWhereAdded2(): void
|
||||
{
|
||||
$params = SearchParams
|
||||
::create()
|
||||
->withWhereAdded(
|
||||
WhereItem::fromRaw([
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 'a2',
|
||||
])
|
||||
);
|
||||
|
||||
$where = $params->getWhere();
|
||||
|
||||
$this->assertEquals(WhereItem\Type::AND, $where->getType());
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'type' => WhereItem\Type::AND,
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'isTrue',
|
||||
'attribute' => 'a2',
|
||||
'value' => null,
|
||||
],
|
||||
],
|
||||
],
|
||||
$where->getRaw()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWithBoolFilterAdded(): void
|
||||
{
|
||||
$params = SearchParams
|
||||
::create()
|
||||
->withBoolFilterList(['test1']);
|
||||
|
||||
$this->assertEquals(
|
||||
['test1', 'test2'],
|
||||
$params->withBoolFilterAdded('test2')->getBoolFilterList()
|
||||
);
|
||||
}
|
||||
}
|
||||
311
tests/unit/Espo/Core/Select/SelectBuilderTest.php
Normal file
311
tests/unit/Espo/Core/Select/SelectBuilderTest.php
Normal file
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select;
|
||||
|
||||
use Espo\Core\Select\AccessControl\Applier as AccessControlFilterApplier;
|
||||
use Espo\Core\Select\Applier\Appliers\Additional as AdditionalApplier;
|
||||
use Espo\Core\Select\Applier\Appliers\Limit as LimitApplier;
|
||||
use Espo\Core\Select\Applier\Factory as ApplierFactory;
|
||||
use Espo\Core\Select\Bool\Applier as BoolFilterListApplier;
|
||||
use Espo\Core\Select\Order\Applier as OrderApplier;
|
||||
use Espo\Core\Select\Order\Params as OrderParams;
|
||||
use Espo\Core\Select\Primary\Applier as PrimaryFilterApplier;
|
||||
use Espo\Core\Select\SearchParams;
|
||||
use Espo\Core\Select\Select\Applier as SelectApplier;
|
||||
use Espo\Core\Select\SelectBuilder;
|
||||
use Espo\Core\Select\Text\Applier as TextFilterApplier;
|
||||
use Espo\Core\Select\Text\FilterParams as TextFilterParams;
|
||||
use Espo\Core\Select\Where\Applier as WhereApplier;
|
||||
use Espo\Core\Select\Where\Params as WhereParams;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SelectBuilderTest extends TestCase
|
||||
{
|
||||
/** @var SelectBuilder */
|
||||
private $selectBuilder;
|
||||
|
||||
private $additionalApplier;
|
||||
private $entityType;
|
||||
private $whereApplier;
|
||||
private $orderApplier;
|
||||
private $limitApplier;
|
||||
private $accessControlFilterApplier;
|
||||
private $textFilterApplier;
|
||||
private $primaryFilterApplier;
|
||||
private $boolFilterListApplier;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$user = $this->createMock(User::class);
|
||||
$applierFactory = $this->createMock(ApplierFactory::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->whereApplier = $this->createMock(WhereApplier::class);
|
||||
$selectApplier = $this->createMock(SelectApplier::class);
|
||||
$this->orderApplier = $this->createMock(OrderApplier::class);
|
||||
$this->limitApplier = $this->createMock(LimitApplier::class);
|
||||
$this->accessControlFilterApplier = $this->createMock(AccessControlFilterApplier::class);
|
||||
$this->textFilterApplier = $this->createMock(TextFilterApplier::class);
|
||||
$this->primaryFilterApplier = $this->createMock(PrimaryFilterApplier::class);
|
||||
$this->boolFilterListApplier = $this->createMock(BoolFilterListApplier::class);
|
||||
$this->additionalApplier = $this->createMock(AdditionalApplier::class);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createWhere')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->whereApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createSelect')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($selectApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createOrder')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->orderApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createLimit')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->limitApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createAccessControlFilter')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->accessControlFilterApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createTextFilter')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->textFilterApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createPrimaryFilter')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->primaryFilterApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createBoolFilterList')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->boolFilterListApplier);
|
||||
|
||||
$applierFactory
|
||||
->expects($this->any())
|
||||
->method('createAdditional')
|
||||
->with($this->entityType, $user)
|
||||
->willReturn($this->additionalApplier);
|
||||
|
||||
$this->selectBuilder = new SelectBuilder($user, $applierFactory);
|
||||
}
|
||||
|
||||
public function testBuild1()
|
||||
{
|
||||
$raw = [
|
||||
'textFilter' => 'testText',
|
||||
'primaryFilter' => 'testPrimary',
|
||||
'boolFilterList' => [
|
||||
'testBool1',
|
||||
'testBool2',
|
||||
],
|
||||
'where' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test',
|
||||
'value' => 'value',
|
||||
],
|
||||
],
|
||||
'orderBy' => 'test',
|
||||
'order' => SearchParams::ORDER_DESC,
|
||||
];
|
||||
|
||||
$searchParams = SearchParams::fromRaw($raw);
|
||||
|
||||
$this->primaryFilterApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
$this->isInstanceOf(QueryBuilder::class),
|
||||
$raw['primaryFilter']
|
||||
);
|
||||
|
||||
$this->boolFilterListApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
$this->isInstanceOf(QueryBuilder::class),
|
||||
[
|
||||
'testBool1',
|
||||
'testBool2',
|
||||
'testBool3',
|
||||
]
|
||||
);
|
||||
|
||||
$textFilterParams = TextFilterParams::create();
|
||||
|
||||
$this->textFilterApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
$this->isInstanceOf(QueryBuilder::class),
|
||||
$raw['textFilter'],
|
||||
$textFilterParams
|
||||
);
|
||||
|
||||
$this->accessControlFilterApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
$this->isInstanceOf(QueryBuilder::class)
|
||||
);
|
||||
|
||||
$whereItem = $searchParams->getWhere();
|
||||
|
||||
$whereParams = WhereParams::fromAssoc([
|
||||
'applyPermissionCheck' => true,
|
||||
'forbidComplexExpressions' => true,
|
||||
]);
|
||||
|
||||
$this->whereApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
$this->isInstanceOf(QueryBuilder::class),
|
||||
$whereItem,
|
||||
$whereParams
|
||||
);
|
||||
|
||||
$orderParams = OrderParams::fromAssoc([
|
||||
'orderBy' => $searchParams->getOrderBy(),
|
||||
'order' => $searchParams->getOrder(),
|
||||
'applyPermissionCheck' => true,
|
||||
]);
|
||||
|
||||
$this->orderApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
$this->isInstanceOf(QueryBuilder::class),
|
||||
$orderParams
|
||||
);
|
||||
|
||||
$this->additionalApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
[],
|
||||
$this->isInstanceOf(QueryBuilder::class),
|
||||
$this->isInstanceOf(SearchParams::class),
|
||||
);
|
||||
|
||||
$query = $this->selectBuilder
|
||||
->from($this->entityType)
|
||||
->withSearchParams($searchParams)
|
||||
->withStrictAccessControl()
|
||||
->withBoolFilter('testBool3')
|
||||
->build();
|
||||
|
||||
$this->assertEquals($this->entityType, $query->getFrom());
|
||||
}
|
||||
|
||||
public function testBuildDefaultOrder1()
|
||||
{
|
||||
$raw = [
|
||||
'textFilter' => 'testText',
|
||||
];
|
||||
|
||||
$searchParams = SearchParams::fromRaw($raw);
|
||||
|
||||
$orderParams = OrderParams::fromAssoc([
|
||||
'forceDefault' => true,
|
||||
'order' => null,
|
||||
]);
|
||||
|
||||
$this->orderApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with(
|
||||
$this->isInstanceOf(QueryBuilder::class),
|
||||
$orderParams
|
||||
);
|
||||
|
||||
$query = $this->selectBuilder
|
||||
->from($this->entityType)
|
||||
->withSearchParams($searchParams)
|
||||
->build();
|
||||
|
||||
$this->assertEquals($this->entityType, $query->getFrom());
|
||||
}
|
||||
|
||||
public function testBuildClone1()
|
||||
{
|
||||
$query = (new QueryBuilder())
|
||||
->from($this->entityType)
|
||||
->build();
|
||||
|
||||
$query = $this->selectBuilder
|
||||
->clone($query)
|
||||
->withPrimaryFilter('testPrimary')
|
||||
->build();
|
||||
|
||||
$this->assertEquals($this->entityType, $query->getFrom());
|
||||
}
|
||||
|
||||
public function testBuildMaxSize0()
|
||||
{
|
||||
|
||||
$searchParams = SearchParams::create()->withMaxSize(0);
|
||||
|
||||
|
||||
$this->limitApplier
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with($this->isInstanceOf(QueryBuilder::class), 0, 0);
|
||||
|
||||
$query = $this->selectBuilder
|
||||
->from($this->entityType)
|
||||
->withSearchParams($searchParams)
|
||||
->build();
|
||||
|
||||
$this->assertEquals($this->entityType, $query->getFrom());
|
||||
}
|
||||
}
|
||||
42
tests/unit/Espo/Core/Select/Text/FilterParamsTest.php
Normal file
42
tests/unit/Espo/Core/Select/Text/FilterParamsTest.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Text;
|
||||
|
||||
use Espo\Core\Select\Text\FilterParams;
|
||||
|
||||
class FilterParamsTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testCreate1(): void
|
||||
{
|
||||
$item = FilterParams::create();
|
||||
|
||||
$this->assertNotNull($item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Text;
|
||||
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\Text\FullTextSearch\DataComposerFactory as FullTextSearchDataComposerFactory;
|
||||
use Espo\Core\Select\Text\FullTextSearch\DefaultDataComposer as FullTextSearchDataComposer;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FullTextSearchDataComposerFactoryTest extends TestCase
|
||||
{
|
||||
private $injectableFactory;
|
||||
private $metadata;
|
||||
private $factory;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
|
||||
$this->factory = new FullTextSearchDataComposerFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(null);
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest('SomeClass');
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$defaultClassName = FullTextSearchDataComposer::class;
|
||||
|
||||
$this->metadata
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with([
|
||||
'selectDefs', $entityType, 'fullTextSearchDataComposerClassName'
|
||||
])
|
||||
->willReturn($className);
|
||||
|
||||
$className = $className ?? $defaultClassName;
|
||||
|
||||
$object = $this->createMock($defaultClassName);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWith')
|
||||
->with(
|
||||
$className,
|
||||
[
|
||||
'entityType' => $entityType,
|
||||
]
|
||||
)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create($entityType);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Text;
|
||||
|
||||
use Espo\Core\Select\Text\FullTextSearch\DataComposer\Params;
|
||||
|
||||
class FullTextSearchDataComposerParamsTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testCreate()
|
||||
{
|
||||
$item = Params::create();
|
||||
|
||||
$this->assertNotNull($item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Text;
|
||||
|
||||
use Espo\Core\Select\Text\FullTextSearch\DataComposer\Params as FullTextSearchDataComposerParams;
|
||||
use Espo\Core\Select\Text\FullTextSearch\DefaultDataComposer as FullTextSearchDataComposer;
|
||||
use Espo\Core\Select\Text\MetadataProvider;
|
||||
use Espo\Core\Utils\Config;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FullTextSearchDataComposerTest extends TestCase
|
||||
{
|
||||
private $config;
|
||||
private $metadataProvider;
|
||||
private $entityType;
|
||||
private $fullTextSearchDataComposer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->config = $this->createMock(Config::class);
|
||||
$this->metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->fullTextSearchDataComposer = new FullTextSearchDataComposer(
|
||||
$this->entityType,
|
||||
$this->config,
|
||||
$this->metadataProvider
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompose1()
|
||||
{
|
||||
$filter = 'test filter';
|
||||
|
||||
$this->config
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
['fullTextSearchDisabled', false],
|
||||
['fullTextSearchMinLength', 4],
|
||||
]
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('isFieldNotStorable')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
[$this->entityType, 'field1', false],
|
||||
[$this->entityType, 'field2', false],
|
||||
[$this->entityType, 'field3', false],
|
||||
]
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('isFullTextSearchSupportedForField')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
[$this->entityType, 'field1', true],
|
||||
[$this->entityType, 'field2', true],
|
||||
[$this->entityType, 'field3', false],
|
||||
]
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('hasFullTextSearch')
|
||||
->with($this->entityType)
|
||||
->willReturn(true);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getFullTextSearchColumnList')
|
||||
->with($this->entityType)
|
||||
->willReturn(
|
||||
['field1A', 'field1B', 'field2']
|
||||
);
|
||||
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
->method('getTextFilterAttributeList')
|
||||
->with($this->entityType)
|
||||
->willReturn(
|
||||
['field1', 'field2', 'field3']
|
||||
);
|
||||
|
||||
$params = FullTextSearchDataComposerParams::create();
|
||||
|
||||
$data = $this->fullTextSearchDataComposer->compose($filter, $params);
|
||||
|
||||
$this->assertNotEquals(null, $data);
|
||||
|
||||
$this->assertEquals(['field1A', 'field1B', 'field2'], $data->getColumnList());
|
||||
$this->assertEquals(['field1', 'field2'], $data->getFieldList());
|
||||
|
||||
$this->assertEquals(
|
||||
'MATCH_BOOLEAN:(field1A, field1B, field2, \'test filter\')',
|
||||
$data->getExpression()->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompose2()
|
||||
{
|
||||
$filter = 'bad';
|
||||
|
||||
$this->config
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
['fullTextSearchDisabled', false],
|
||||
['fullTextSearchMinLength', 4],
|
||||
]
|
||||
);
|
||||
|
||||
$params = FullTextSearchDataComposerParams::create();
|
||||
|
||||
$data = $this->fullTextSearchDataComposer->compose($filter, $params);
|
||||
|
||||
$this->assertEquals(null, $data);
|
||||
}
|
||||
|
||||
public function testCompose3()
|
||||
{
|
||||
$filter = 'test filter';
|
||||
|
||||
$this->config
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
['fullTextSearchDisabled', true],
|
||||
['fullTextSearchMinLength', 4],
|
||||
]
|
||||
);
|
||||
|
||||
$params = FullTextSearchDataComposerParams::create();
|
||||
|
||||
$data = $this->fullTextSearchDataComposer->compose($filter, $params);
|
||||
|
||||
$this->assertEquals(null, $data);
|
||||
}
|
||||
}
|
||||
47
tests/unit/Espo/Core/Select/Text/FullTextSearchDataTest.php
Normal file
47
tests/unit/Espo/Core/Select/Text/FullTextSearchDataTest.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Text;
|
||||
|
||||
use Espo\ORM\Query\Part\Expression as Expr;
|
||||
use Espo\Core\Select\Text\FullTextSearch\Data;
|
||||
use Espo\Core\Select\Text\FullTextSearch\Mode;
|
||||
|
||||
class FullTextSearchDataTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGet1(): void
|
||||
{
|
||||
$item = new Data(Expr::create('TEST:()'), ['test'], ['column'], Mode::BOOLEAN);
|
||||
|
||||
$this->assertEquals('TEST:()', $item->getExpression()->getValue());
|
||||
$this->assertEquals(['test'], $item->getFieldList());
|
||||
$this->assertEquals(['column'], $item->getColumnList());
|
||||
$this->assertEquals(Mode::BOOLEAN, $item->getMode());
|
||||
}
|
||||
}
|
||||
105
tests/unit/Espo/Core/Select/Where/CheckerFactoryTest.php
Normal file
105
tests/unit/Espo/Core/Select/Where/CheckerFactoryTest.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\Utils\Acl\UserAclManagerProvider;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\AclManager;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\Where\Checker;
|
||||
use Espo\Core\Select\Where\CheckerFactory;
|
||||
use Espo\Entities\User;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CheckerFactoryTest extends TestCase
|
||||
{
|
||||
private $injectableFactory;
|
||||
private $user;
|
||||
private $acl;
|
||||
private $factory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$aclManager = $this->createMock(AclManager::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->acl = $this->createMock(Acl::class);
|
||||
$userAclFilterResolver = $this->createMock(UserAclManagerProvider::class);
|
||||
|
||||
$aclManager
|
||||
->expects($this->any())
|
||||
->method('createUserAcl')
|
||||
->with($this->user)
|
||||
->willReturn($this->acl);
|
||||
|
||||
$userAclFilterResolver
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->with($this->user)
|
||||
->willReturn($aclManager);
|
||||
|
||||
$this->factory = new CheckerFactory(
|
||||
$this->injectableFactory,
|
||||
$userAclFilterResolver
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest();
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest()
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$object = $this->createMock(Checker::class);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWith')
|
||||
->with(
|
||||
Checker::class,
|
||||
[
|
||||
'entityType' => $entityType,
|
||||
'acl' => $this->acl,
|
||||
]
|
||||
)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create(
|
||||
$entityType,
|
||||
$this->user
|
||||
);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
}
|
||||
}
|
||||
525
tests/unit/Espo/Core/Select/Where/CheckerTest.php
Normal file
525
tests/unit/Espo/Core/Select/Where/CheckerTest.php
Normal file
@@ -0,0 +1,525 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\Acl\Table;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Select\Helpers\EntityHelper;
|
||||
use Espo\Core\Select\Where\Checker;
|
||||
use Espo\Core\Select\Where\Item;
|
||||
use Espo\Core\Select\Where\Params;
|
||||
use Espo\ORM\BaseEntity as Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CheckerTest extends TestCase
|
||||
{
|
||||
/** @var Checker|null */
|
||||
protected $checker = null;
|
||||
protected ?EntityManager $entityManager = null;
|
||||
/** @var Acl|null */
|
||||
protected $acl = null;
|
||||
|
||||
protected ?EntityHelper $entityHelper = null;
|
||||
|
||||
protected ?string $entityType = null;
|
||||
protected ?string $foreignEntityType = null;
|
||||
|
||||
private $entity;
|
||||
private $params;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->entityManager = $this->createMock(EntityManager::class);
|
||||
$this->acl = $this->createMock(Acl::class);
|
||||
$systemRestriction = $this->createMock(Acl\SystemRestriction::class);
|
||||
$this->entityHelper = $this->createMock(EntityHelper::class);
|
||||
|
||||
$systemRestriction
|
||||
->method('checkAttributeRead')
|
||||
->willReturn(true);
|
||||
|
||||
$systemRestriction
|
||||
->method('checkLinkRead')
|
||||
->willReturn(true);
|
||||
|
||||
$systemRestriction
|
||||
->method('checkFieldRead')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entityType = 'Test';
|
||||
$this->foreignEntityType = 'TestForeign';
|
||||
|
||||
$this->checker = new Checker(
|
||||
entityType: $this->entityType,
|
||||
entityManager: $this->entityManager,
|
||||
acl: $this->acl,
|
||||
systemRestriction: $systemRestriction,
|
||||
entityHelper: $this->entityHelper,
|
||||
);
|
||||
|
||||
$this->params = $this->createMock(Params::class);
|
||||
$this->entity = $this->createMock(Entity::class);
|
||||
$foreignEntity = $this->createMock(Entity::class);
|
||||
|
||||
$this->entityManager
|
||||
->expects($this->any())
|
||||
->method('getNewEntity')
|
||||
->willReturnMap([
|
||||
[$this->entityType, $this->entity],
|
||||
[$this->foreignEntityType, $foreignEntity],
|
||||
]);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testAttributeExistence1()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(false);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'TEST:(test2)',
|
||||
'value' => 'value2',
|
||||
],
|
||||
[
|
||||
'type' => 'linkedWith',
|
||||
'attribute' => 'test3',
|
||||
'value' => 'value3',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects(self::any())
|
||||
->method('hasAttribute')
|
||||
->willReturnMap([
|
||||
['test1', true],
|
||||
['test2', true],
|
||||
]);
|
||||
|
||||
$this->entityHelper
|
||||
->method('getRelationEntityType')
|
||||
->willReturnMap([
|
||||
[$this->entity, 'test3', 'AnotherEntity'],
|
||||
]);
|
||||
|
||||
$another = $this->createMock(Entity::class);
|
||||
|
||||
$this->entityManager
|
||||
->method('getEntityById')
|
||||
->willReturnMap([
|
||||
['AnotherEntity', 'value3', $another]
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->method('hasRelation')
|
||||
->with('test3')
|
||||
->willReturn(true);
|
||||
|
||||
$this->checker->check($item, $this->params);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testAttributeExistence2()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(false);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects(self::any())
|
||||
->method('hasAttribute')
|
||||
->willReturnMap([
|
||||
['test1', false]
|
||||
]);
|
||||
|
||||
$this->expectException(BadRequest::class);
|
||||
|
||||
$this->checker->check($item, $this->params);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testAttributeExistence3()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(false);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'linkedWith',
|
||||
'attribute' => 'test3',
|
||||
'value' => 'value3',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects($this->once())
|
||||
->method('hasRelation')
|
||||
->with('test3')
|
||||
->willReturn(false);
|
||||
|
||||
$this->expectException(BadRequest::class);
|
||||
|
||||
$this->checker->check($item, $this->params);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testPermissions1()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(true);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test3.test2',
|
||||
'value' => 'value2',
|
||||
],
|
||||
[
|
||||
'type' => 'linkedWith',
|
||||
'attribute' => 'test3',
|
||||
'value' => 'value3',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasAttribute')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasRelation')
|
||||
->with('test3')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('getRelationParam')
|
||||
->with('test3', 'entity')
|
||||
->willReturn($this->foreignEntityType);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('getScopeForbiddenAttributeList')
|
||||
->willReturnMap([
|
||||
[$this->entityType, Table::ACTION_READ, Table::LEVEL_NO, []],
|
||||
[$this->foreignEntityType, Table::ACTION_READ, Table::LEVEL_NO, []],
|
||||
]);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('getScopeForbiddenFieldList')
|
||||
->with($this->entityType)
|
||||
->willReturn([]);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('getScopeForbiddenLinkList')
|
||||
->with($this->entityType)
|
||||
->willReturn([]);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('checkScope')
|
||||
->with($this->foreignEntityType)
|
||||
->willReturn(true);
|
||||
|
||||
$foreign = $this->createMock(Entity::class);
|
||||
|
||||
$this->entityManager
|
||||
->expects($this->any())
|
||||
->method('getEntityById')
|
||||
->willReturnMap([
|
||||
[$this->foreignEntityType, 'value3', $foreign]
|
||||
]);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('checkEntityRead')
|
||||
->willReturnMap([
|
||||
[$foreign, true]
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->method('hasRelation')
|
||||
->with('test3')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entityHelper
|
||||
->method('getRelationEntityType')
|
||||
->willReturnMap([
|
||||
[$this->entity, 'test3', $this->foreignEntityType],
|
||||
]);
|
||||
|
||||
$this->checker->check($item, $this->params);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testPermissions2()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(true);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasAttribute')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasRelation')
|
||||
->with('test3')
|
||||
->willReturn(true);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('getScopeForbiddenAttributeList')
|
||||
->with($this->entityType)
|
||||
->willReturn(['test1']);
|
||||
|
||||
$this->expectException(Forbidden::class);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$this->checker->check($item, $this->params);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testPermissions3()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(true);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test3.test2',
|
||||
'value' => 'value2',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasAttribute')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasRelation')
|
||||
->with('test3')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('getRelationParam')
|
||||
->with('test3', 'entity')
|
||||
->willReturn($this->foreignEntityType);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('checkScope')
|
||||
->with($this->foreignEntityType)
|
||||
->willReturn(false);
|
||||
|
||||
$this->expectException(Forbidden::class);
|
||||
|
||||
$this->checker->check($item, $this->params);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testPermissions4()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(true);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'linkedWith',
|
||||
'attribute' => 'test3',
|
||||
'value' => 'value3',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasAttribute')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasRelation')
|
||||
->with('test3')
|
||||
->willReturn(true);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('getRelationParam')
|
||||
->with('test3', 'entity')
|
||||
->willReturn($this->foreignEntityType);
|
||||
|
||||
$this->acl
|
||||
->expects($this->any())
|
||||
->method('checkScope')
|
||||
->with($this->foreignEntityType)
|
||||
->willReturn(false);
|
||||
|
||||
$this->expectException(Forbidden::class);
|
||||
|
||||
$this->checker->check($item, $this->params);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testComplexExpressions1()
|
||||
{
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forbidComplexExpressions')
|
||||
->willReturn(true);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('applyPermissionCheck')
|
||||
->willReturn(false);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'TEST:(test2)',
|
||||
'value' => 'value2',
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$this->expectException(Forbidden::class);
|
||||
|
||||
$this->checker->check($item, $this->params);
|
||||
}
|
||||
}
|
||||
180
tests/unit/Espo/Core/Select/Where/ConverterFactoryTest.php
Normal file
180
tests/unit/Espo/Core/Select/Where/ConverterFactoryTest.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\Where\Converter;
|
||||
use Espo\Core\Select\Where\ConverterFactory;
|
||||
use Espo\Core\Select\Where\DateTimeItemTransformer;
|
||||
use Espo\Core\Select\Where\DefaultDateTimeItemTransformer;
|
||||
use Espo\Core\Select\Where\ItemConverter;
|
||||
use Espo\Core\Select\Where\ItemGeneralConverter;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
class ConverterFactoryTest extends TestCase
|
||||
{
|
||||
private $injectableFactory;
|
||||
private $metadata;
|
||||
private $user;
|
||||
private $factory;
|
||||
private $itemConverter;
|
||||
private $dateTimeItemTransformer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$this->factory = new ConverterFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata
|
||||
);
|
||||
|
||||
$this->itemConverter = $this->createMock(ItemGeneralConverter::class);
|
||||
$this->dateTimeItemTransformer = $this->createMock(DefaultDateTimeItemTransformer::class);
|
||||
}
|
||||
|
||||
public function testCreate1()
|
||||
{
|
||||
$this->prepareFactoryTest(null, null, null);
|
||||
}
|
||||
|
||||
public function testCreate2()
|
||||
{
|
||||
$this->prepareFactoryTest('SomeClass1', 'SomeClass2', 'SomeClass3');
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className1, ?string $className2, ?string $className3)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
[['selectDefs', $entityType, 'whereDateTimeItemTransformerClassName'], null, $className1],
|
||||
[['selectDefs', $entityType, 'whereItemConverterClassName'], null, $className2],
|
||||
[['selectDefs', $entityType, 'whereConverterClassName'], null, $className3],
|
||||
]);
|
||||
|
||||
$className1 = $className1 ?? DefaultDateTimeItemTransformer::class;
|
||||
$className2 = $className2 ?? ItemGeneralConverter::class;
|
||||
$className3 = $className3 ?? Converter::class;
|
||||
|
||||
$object = $this->createMock(Converter::class);
|
||||
|
||||
$bindingData1 = new BindingData();
|
||||
|
||||
$binder1 = new Binder($bindingData1);
|
||||
$binder1
|
||||
->bindInstance(User::class, $this->user);
|
||||
$binder1
|
||||
->for($className1)
|
||||
->bindValue('$entityType', $entityType);
|
||||
$binder1
|
||||
->for(DefaultDateTimeItemTransformer::class)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bc1 = new BindingContainer($bindingData1);
|
||||
|
||||
$bindingData2 = new BindingData();
|
||||
|
||||
$binder2 = new Binder($bindingData2);
|
||||
|
||||
$binder2
|
||||
->bindInstance(User::class, $this->user);
|
||||
$binder2
|
||||
->for($className2)
|
||||
->bindValue('$entityType', $entityType)
|
||||
->bindInstance(DateTimeItemTransformer::class, $this->dateTimeItemTransformer);
|
||||
$binder2
|
||||
->for(ItemGeneralConverter::class)
|
||||
->bindValue('$entityType', $entityType)
|
||||
->bindInstance(DateTimeItemTransformer::class, $this->dateTimeItemTransformer);
|
||||
|
||||
$bc2 = new BindingContainer($bindingData2);
|
||||
|
||||
$bindingData3 = new BindingData();
|
||||
|
||||
$binder3 = new Binder($bindingData3);
|
||||
|
||||
$binder3
|
||||
->bindInstance(User::class, $this->user)
|
||||
->for($className3)
|
||||
->bindValue('$entityType', $entityType)
|
||||
->bindInstance(ItemConverter::class, $this->itemConverter);
|
||||
|
||||
$bc3 = new BindingContainer($bindingData3);
|
||||
|
||||
$c = $this->exactly(3);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($c)
|
||||
->method('createWithBinding')
|
||||
->willReturnCallback(function ($className, $bc) use
|
||||
($c, $object, $className1, $className2, $className3, $bc1, $bc2, $bc3) {
|
||||
|
||||
if ($c->numberOfInvocations() === 1) {
|
||||
$this->assertEquals($className1, $className);
|
||||
$this->assertEquals($bc1, $bc);
|
||||
|
||||
return $this->dateTimeItemTransformer;
|
||||
}
|
||||
|
||||
if ($c->numberOfInvocations() === 2) {
|
||||
$this->assertEquals($className2, $className);
|
||||
$this->assertEquals($bc2, $bc);
|
||||
|
||||
return $this->itemConverter;
|
||||
}
|
||||
|
||||
if ($c->numberOfInvocations() === 3) {
|
||||
$this->assertEquals($className3, $className);
|
||||
$this->assertEquals($bc3, $bc);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
throw new RuntimeException();
|
||||
});
|
||||
|
||||
$resultObject = $this->factory->create($entityType, $this->user);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
}
|
||||
}
|
||||
447
tests/unit/Espo/Core/Select/Where/ConverterTest.php
Normal file
447
tests/unit/Espo/Core/Select/Where/ConverterTest.php
Normal file
@@ -0,0 +1,447 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\Select\Helpers\RandomStringGenerator;
|
||||
use Espo\Core\Select\Where\Converter;
|
||||
use Espo\Core\Select\Where\DefaultDateTimeItemTransformer;
|
||||
use Espo\Core\Select\Where\Item;
|
||||
use Espo\Core\Select\Where\ItemConverter;
|
||||
use Espo\Core\Select\Where\ItemConverterFactory;
|
||||
use Espo\Core\Select\Where\ItemGeneralConverter;
|
||||
use Espo\Core\Select\Where\Scanner;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Defs as ORMDefs;
|
||||
use Espo\ORM\Defs\EntityDefs;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Metadata as ormMetadata;
|
||||
use Espo\ORM\Query\Part\Join\JoinType;
|
||||
use Espo\ORM\Query\Part\WhereClause;
|
||||
use Espo\ORM\Query\Select;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use Espo\ORM\QueryBuilder as BaseQueryBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ConverterTest extends TestCase
|
||||
{
|
||||
private $entityType;
|
||||
private $user;
|
||||
private $scanner;
|
||||
private $itemConverterFactory;
|
||||
private $ormDefs;
|
||||
private $queryBuilder;
|
||||
private $converter;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->entityType = 'Test';
|
||||
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$config = $this->createMock(Config::class);
|
||||
$applicationConfig = $this->createMock(Config\ApplicationConfig::class);
|
||||
$metadata = $this->createMock(Metadata::class);
|
||||
|
||||
$this->scanner = $this->createMock(Scanner::class);
|
||||
$randomStringGenerator = $this->createMock(RandomStringGenerator::class);
|
||||
$this->itemConverterFactory = $this->createMock(ItemConverterFactory::class);
|
||||
|
||||
$entityManager = $this->createMock(EntityManager::class);
|
||||
$ormMetadata = $this->createMock(ormMetadata::class);
|
||||
|
||||
$baseQueryBuilder = $this->createMock(BaseQueryBuilder::class);
|
||||
|
||||
$entityManager
|
||||
->expects($this->any())
|
||||
->method('getMetadata')
|
||||
->willReturn($ormMetadata);
|
||||
|
||||
$entityManager
|
||||
->expects($this->any())
|
||||
->method('getQueryBuilder')
|
||||
->willReturn($baseQueryBuilder);
|
||||
|
||||
$this->ormDefs = $this->createMock(ORMDefs::class);
|
||||
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
|
||||
$randomStringGenerator
|
||||
->expects($this->any())
|
||||
->method('generate')
|
||||
->willReturn('Random');
|
||||
|
||||
$applicationConfig
|
||||
->expects($this->any())
|
||||
->method('getTimeZone')
|
||||
->willReturn('UTC');
|
||||
|
||||
$dateTimeItemTransformer = new DefaultDateTimeItemTransformer($config, $applicationConfig);
|
||||
|
||||
$itemConverter = new ItemGeneralConverter(
|
||||
$this->entityType,
|
||||
$this->user,
|
||||
$dateTimeItemTransformer,
|
||||
$this->scanner,
|
||||
$this->itemConverterFactory,
|
||||
$randomStringGenerator,
|
||||
$this->ormDefs,
|
||||
$config,
|
||||
$metadata,
|
||||
$applicationConfig,
|
||||
);
|
||||
|
||||
$this->converter = new Converter(
|
||||
$itemConverter,
|
||||
$this->scanner
|
||||
);
|
||||
}
|
||||
|
||||
public function testConvertApplyLeftJoins()
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
],
|
||||
]);
|
||||
|
||||
$this->scanner
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with($this->queryBuilder, $item);
|
||||
|
||||
$this->converter->convert($this->queryBuilder, $item);
|
||||
}
|
||||
|
||||
public function testConvertEquals1()
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test',
|
||||
'value' => 'test-value',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$whereClause = $this->converter->convert($this->queryBuilder, $item);
|
||||
|
||||
$expected = [
|
||||
'test=' => 'test-value',
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $whereClause->getRaw());
|
||||
}
|
||||
|
||||
public function testConvertEquals2()
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test2',
|
||||
'value' => 'value2',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$whereClause = $this->converter->convert($this->queryBuilder, $item);
|
||||
|
||||
$expected = [
|
||||
['test1=' => 'value1'],
|
||||
['test2=' => 'value2'],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $whereClause->getRaw());
|
||||
}
|
||||
|
||||
public function testConvertOr()
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'or',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
[
|
||||
'type' => 'notEquals',
|
||||
'attribute' => 'test2',
|
||||
'value' => 'value2',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
]);
|
||||
|
||||
$whereClause = $this->converter->convert($this->queryBuilder, $item);
|
||||
|
||||
$expected = [
|
||||
'OR' => [
|
||||
['test1=' => 'value1'],
|
||||
['test2!=' => 'value2'],
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $whereClause->getRaw());
|
||||
}
|
||||
|
||||
public function testConvertDateTimeOn1()
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'on',
|
||||
'attribute' => 'test',
|
||||
'value' => '2020-12-20',
|
||||
'dateTime' => true,
|
||||
'timeZone' => 'Europe/Kyiv',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$whereClause = $this->converter->convert($this->queryBuilder, $item);
|
||||
|
||||
$expected = [
|
||||
'AND' => [
|
||||
'test>=' => '2020-12-19 22:00:00',
|
||||
'test<=' => '2020-12-20 21:59:59',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $whereClause->getRaw());
|
||||
}
|
||||
|
||||
public function testConvertSubQueryIn()
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'subQueryIn',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
]);
|
||||
|
||||
$sqItem = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value1',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$c = $this->exactly(2);
|
||||
|
||||
$this->scanner
|
||||
->expects($c)
|
||||
->method('apply')
|
||||
->willReturnCallback(function ($qb, $it) use ($c, $sqItem, $item) {
|
||||
if ($c->numberOfInvocations() === 1) {
|
||||
$this->assertEquals($sqItem, $it);
|
||||
}
|
||||
|
||||
if ($c->numberOfInvocations() === 2) {
|
||||
$this->assertEquals($item, $it);
|
||||
}
|
||||
});
|
||||
|
||||
$whereClause = $this->converter->convert($this->queryBuilder, $item);
|
||||
|
||||
$expected = [
|
||||
'id=s' => Select::fromRaw([
|
||||
'select' => ['id'],
|
||||
'from' => $this->entityType,
|
||||
'whereClause' => [
|
||||
'AND' => [
|
||||
['test1=' => 'value1'],
|
||||
],
|
||||
],
|
||||
'leftJoins' => [],
|
||||
'joins' => [],
|
||||
]),
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $whereClause->getRaw());
|
||||
}
|
||||
|
||||
public function testConvertLinkedWith1()
|
||||
{
|
||||
$link = 'test';
|
||||
|
||||
$value = ['value-id'];
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'linkedWith',
|
||||
'attribute' => $link,
|
||||
'value' => $value,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->ormDefs
|
||||
->expects($this->any())
|
||||
->method('getEntity')
|
||||
->with($this->entityType)
|
||||
->willReturn(
|
||||
EntityDefs::fromRaw(
|
||||
[
|
||||
'relations' => [
|
||||
$link => [
|
||||
'type' => Entity::MANY_MANY,
|
||||
'entity' => 'Foreign',
|
||||
'midKeys' => ['localId', 'foreignId'],
|
||||
'relationName' => 'entityEntity'
|
||||
],
|
||||
],
|
||||
],
|
||||
$this->entityType
|
||||
)
|
||||
);
|
||||
|
||||
$alias = $link . 'LinkedWithFilterRandom';
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->never())
|
||||
->method('distinct');
|
||||
|
||||
|
||||
$expected = [
|
||||
'id=s' => Select::fromRaw([
|
||||
'select' => ['id'],
|
||||
'from' => 'Test',
|
||||
'joins' => [
|
||||
[
|
||||
'test',
|
||||
$alias,
|
||||
null,
|
||||
[
|
||||
'onlyMiddle' => true,
|
||||
'type' => JoinType::left,
|
||||
],
|
||||
],
|
||||
],
|
||||
'whereClause' => [
|
||||
$alias . '.foreignId' => $value,
|
||||
],
|
||||
]),
|
||||
];
|
||||
|
||||
$whereClause = $this->converter->convert($this->queryBuilder, $item);
|
||||
|
||||
$this->assertEquals($expected, $whereClause->getRaw());
|
||||
}
|
||||
|
||||
public function testConvertCustomConverter()
|
||||
{
|
||||
$type = 'testType';
|
||||
$attribute = 'testAttribute';
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => $type,
|
||||
'attribute' => $attribute,
|
||||
'value' => 'test-value',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$subItem = Item::fromRaw([
|
||||
'type' => $type,
|
||||
'attribute' => $attribute,
|
||||
'value' => 'test-value',
|
||||
]);
|
||||
|
||||
$converter = $this->createMock(ItemConverter::class);
|
||||
|
||||
$converter
|
||||
->expects($this->once())
|
||||
->method('convert')
|
||||
->with($this->queryBuilder, $subItem)
|
||||
->willReturn(
|
||||
WhereClause::fromRaw([
|
||||
'testAnother=' => 'test-value',
|
||||
])
|
||||
);
|
||||
|
||||
$this->itemConverterFactory
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with($this->entityType, $attribute, $type)
|
||||
->willReturn(true);
|
||||
|
||||
$this->itemConverterFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $attribute, $type, $this->user)
|
||||
->willReturn($converter);
|
||||
|
||||
$whereClause = $this->converter->convert($this->queryBuilder, $item);
|
||||
|
||||
$expected = [
|
||||
'testAnother=' => 'test-value',
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $whereClause->getRaw());
|
||||
}
|
||||
}
|
||||
204
tests/unit/Espo/Core/Select/Where/ItemConverterFactoryTest.php
Normal file
204
tests/unit/Espo/Core/Select/Where/ItemConverterFactoryTest.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Select\Where\ItemConverterFactory;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\User;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use tests\unit\testClasses\Core\Select\Where\ItemConverters\TestConverter;
|
||||
|
||||
class ItemConverterFactoryTest extends TestCase
|
||||
{
|
||||
private $metadata;
|
||||
private $injectableFactory;
|
||||
private $user;
|
||||
private $factory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$this->factory = new ItemConverterFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreateForType()
|
||||
{
|
||||
$this->prepareFactoryTest(TestConverter::class);
|
||||
$this->prepareFactoryTest(TestConverter::class, true);
|
||||
}
|
||||
|
||||
public function testHasFalseForType()
|
||||
{
|
||||
$this->metadata
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with([
|
||||
'app', 'select', 'whereItemConverterClassNameMap', 'someType'
|
||||
])
|
||||
->willReturn(null);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->factory->hasForType('someType')
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreateEntityType()
|
||||
{
|
||||
$this->prepareFactoryTestEntityType(TestConverter::class);
|
||||
$this->prepareFactoryTestEntityType(TestConverter::class, true);
|
||||
}
|
||||
|
||||
protected function prepareFactoryTest(?string $className, bool $testHas = false)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$type = 'someType';
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->with([
|
||||
'app', 'select', 'whereItemConverterClassNameMap', $type
|
||||
])
|
||||
->willReturn($className);
|
||||
|
||||
if ($testHas) {
|
||||
$this->assertTrue(
|
||||
$this->factory->hasForType($type)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$object = $this->createMock($className);
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $this->user);
|
||||
|
||||
$binder
|
||||
->for($className)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bindingContainer = new BindingContainer($bindingData);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWithBinding')
|
||||
->with(
|
||||
$className,
|
||||
$bindingContainer
|
||||
)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->createForType(
|
||||
$type,
|
||||
$entityType,
|
||||
$this->user
|
||||
);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
}
|
||||
|
||||
protected function prepareFactoryTestEntityType(?string $className, bool $testHas = false)
|
||||
{
|
||||
$entityType = 'Test';
|
||||
|
||||
$type = 'someType';
|
||||
|
||||
$attribute = 'test';
|
||||
|
||||
$this->metadata
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->with([
|
||||
'selectDefs', $entityType, 'whereItemConverterClassNameMap', $attribute . '_' . $type
|
||||
])
|
||||
->willReturn($className);
|
||||
|
||||
if ($testHas) {
|
||||
$this->assertTrue(
|
||||
$this->factory->has(
|
||||
$entityType,
|
||||
$attribute,
|
||||
$type
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$object = $this->createMock($className);
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $this->user);
|
||||
|
||||
$binder
|
||||
->for($className)
|
||||
->bindValue('$entityType', $entityType);
|
||||
|
||||
$bindingContainer = new BindingContainer($bindingData);
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWithBinding')
|
||||
->with(
|
||||
$className,
|
||||
$bindingContainer
|
||||
)
|
||||
->willReturn($object);
|
||||
|
||||
$resultObject = $this->factory->create(
|
||||
$entityType,
|
||||
$attribute,
|
||||
$type,
|
||||
$this->user
|
||||
);
|
||||
|
||||
$this->assertEquals($object, $resultObject);
|
||||
}
|
||||
}
|
||||
193
tests/unit/Espo/Core/Select/Where/ItemTest.php
Normal file
193
tests/unit/Espo/Core/Select/Where/ItemTest.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\Select\Where\Item;
|
||||
use Espo\Core\Select\Where\Item\Data\DateTime;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class ItemTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testFromArray()
|
||||
{
|
||||
$item = Item::createBuilder()
|
||||
->setType('equals')
|
||||
->setAttribute('test')
|
||||
->setValue('testValue')
|
||||
->build();
|
||||
|
||||
$this->assertEquals('equals', $item->getType());
|
||||
$this->assertEquals('test', $item->getAttribute());
|
||||
$this->assertEquals('testValue', $item->getValue());
|
||||
$this->assertNull($item->getData());
|
||||
|
||||
$item1 = Item::createBuilder()
|
||||
->setType('equals')
|
||||
->setAttribute('test')
|
||||
->setValue(1)
|
||||
->build();
|
||||
|
||||
$this->assertEquals('equals', $item1->getType());
|
||||
$this->assertEquals('test', $item1->getAttribute());
|
||||
$this->assertEquals(1, $item1->getValue());
|
||||
|
||||
$item2 = Item::createBuilder()
|
||||
->setType('equals')
|
||||
->setAttribute('test')
|
||||
->setValue('testValue')
|
||||
->setData(
|
||||
DateTime::create()->withTimeZone('Europe/London')
|
||||
)
|
||||
->build();
|
||||
|
||||
$this->assertNotNull($item2->getData());
|
||||
$this->assertEquals('Europe/London', $item2->getData()->getTimeZone());
|
||||
}
|
||||
|
||||
public function testEmpty()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$item = Item::fromRaw([]);
|
||||
}
|
||||
|
||||
public function testEmptyAttribute1()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'equals',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testEmptyAttribute2()
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [],
|
||||
]);
|
||||
|
||||
$this->assertNotNull($item);
|
||||
}
|
||||
|
||||
public function testEmptyType()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'attribute' => 'test',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testNonExistingParam()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = Item::fromRaw([
|
||||
'bad' => 'd',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testGetRaw1()
|
||||
{
|
||||
$raw = [
|
||||
'type' => 'and',
|
||||
'value' => [],
|
||||
];
|
||||
|
||||
$item = Item::fromRaw($raw);
|
||||
|
||||
$result = $item->getRaw();
|
||||
|
||||
$this->assertEquals($raw, $result);
|
||||
}
|
||||
|
||||
public function testGetRaw2()
|
||||
{
|
||||
$raw = [
|
||||
'type' => 'euqls',
|
||||
'attribute' => 'test',
|
||||
'value' => '2020-12-12',
|
||||
'dateTime' => true,
|
||||
'timeZone' => 'UTC',
|
||||
];
|
||||
|
||||
$item = Item::fromRaw($raw);
|
||||
|
||||
$result = $item->getRaw();
|
||||
|
||||
$this->assertEquals($raw, $result);
|
||||
}
|
||||
|
||||
public function testGetItemList1()
|
||||
{
|
||||
$raw = [
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'or',
|
||||
'value' => [],
|
||||
],
|
||||
[
|
||||
'type' => 'or',
|
||||
'value' => [],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$item = Item::fromRaw($raw);
|
||||
|
||||
$this->assertEquals('or', $item->getItemList()[0]->getType());
|
||||
}
|
||||
|
||||
public function testGetItemList2()
|
||||
{
|
||||
$item = Item::createBuilder()
|
||||
->setType('and')
|
||||
->setItemList([
|
||||
Item::createBuilder()
|
||||
->setType('or')
|
||||
->setItemList([])
|
||||
->build(),
|
||||
Item::createBuilder()
|
||||
->setType('or')
|
||||
->setItemList([])
|
||||
->build(),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->assertEquals('or', $item->getItemList()[0]->getType());
|
||||
}
|
||||
}
|
||||
88
tests/unit/Espo/Core/Select/Where/ParamsTest.php
Normal file
88
tests/unit/Espo/Core/Select/Where/ParamsTest.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\{
|
||||
Select\Where\Params,
|
||||
};
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class ParamsTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function setUp() : void
|
||||
{
|
||||
}
|
||||
|
||||
public function testFromArray()
|
||||
{
|
||||
$item = Params::fromAssoc([
|
||||
'applyPermissionCheck' => true,
|
||||
'forbidComplexExpressions' => true,
|
||||
]);
|
||||
|
||||
$this->assertTrue($item->applyPermissionCheck());
|
||||
$this->assertTrue($item->forbidComplexExpressions());
|
||||
|
||||
$item = Params::fromAssoc([
|
||||
'applyPermissionCheck' => false,
|
||||
'forbidComplexExpressions' => false,
|
||||
]);
|
||||
|
||||
$this->assertFalse($item->applyPermissionCheck());
|
||||
$this->assertFalse($item->forbidComplexExpressions());
|
||||
|
||||
$item = Params::fromAssoc([
|
||||
'applyPermissionCheck' => false,
|
||||
'forbidComplexExpressions' => true,
|
||||
]);
|
||||
|
||||
$this->assertFalse($item->applyPermissionCheck());
|
||||
$this->assertTrue($item->forbidComplexExpressions());
|
||||
}
|
||||
|
||||
public function testEmpty()
|
||||
{
|
||||
$item = Params::fromAssoc([
|
||||
]);
|
||||
|
||||
$this->assertFalse($item->applyPermissionCheck());
|
||||
$this->assertFalse($item->forbidComplexExpressions());
|
||||
}
|
||||
|
||||
public function testNonExistingParam()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$params = Params::fromAssoc([
|
||||
'bad' => 'd',
|
||||
]);
|
||||
}
|
||||
}
|
||||
241
tests/unit/Espo/Core/Select/Where/ScannerTest.php
Normal file
241
tests/unit/Espo/Core/Select/Where/ScannerTest.php
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Where;
|
||||
|
||||
use Espo\Core\Select\Where\Item;
|
||||
use Espo\Core\Select\Where\Scanner;
|
||||
use Espo\ORM\BaseEntity as Entity;
|
||||
use Espo\ORM\Entity as OrmEntity;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\Select as Query;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
use Espo\ORM\Type\RelationType;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ScannerTest extends TestCase
|
||||
{
|
||||
private $scanner;
|
||||
private $queryBuilder;
|
||||
private $entity;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$entityManager = $this->createMock(EntityManager::class);
|
||||
$this->scanner = new Scanner($entityManager);
|
||||
$entityType = 'Test';
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
|
||||
$query = $this->createMock(Query::class);
|
||||
|
||||
$query
|
||||
->expects($this->any())
|
||||
->method('getFrom')
|
||||
->willReturn($entityType);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($this->any())
|
||||
->method('build')
|
||||
->willReturn($query);
|
||||
|
||||
$this->entity = $this->createMock(Entity::class);
|
||||
|
||||
$entityManager
|
||||
->expects($this->any())
|
||||
->method('getNewEntity')
|
||||
->with($entityType)
|
||||
->willReturn($this->entity);
|
||||
}
|
||||
|
||||
public function testApplyLeftJoins1(): void
|
||||
{
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'TEST:(link2.test2)',
|
||||
'value' => 'value',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'link3.test3',
|
||||
'value' => 'value',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test4',
|
||||
'value' => 'value',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('hasRelation')
|
||||
->willReturnMap(
|
||||
[
|
||||
['link1', true],
|
||||
['link2', true],
|
||||
['link3', true],
|
||||
]
|
||||
);
|
||||
|
||||
$c = $this->exactly(3);
|
||||
|
||||
$this->queryBuilder
|
||||
->expects($c)
|
||||
->method('leftJoin')
|
||||
->willReturnCallback(function ($link) use ($c) {
|
||||
if ($c->numberOfInvocations() === 1) {
|
||||
$this->assertEquals('link2', $link);
|
||||
}
|
||||
|
||||
if ($c->numberOfInvocations() === 2) {
|
||||
$this->assertEquals('link3', $link);
|
||||
}
|
||||
|
||||
if ($c->numberOfInvocations() === 3) {
|
||||
$this->assertEquals('link4', $link);
|
||||
}
|
||||
|
||||
return $this->queryBuilder;
|
||||
});
|
||||
|
||||
/*$this->queryBuilder
|
||||
->expects($this->once())
|
||||
->method('distinct');*/
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('getAttributeType')
|
||||
->willReturnMap(
|
||||
[
|
||||
['test1', OrmEntity::VARCHAR],
|
||||
['test4', OrmEntity::FOREIGN],
|
||||
]
|
||||
);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('getRelationType')
|
||||
->willReturnMap(
|
||||
[
|
||||
['link2', OrmEntity::HAS_MANY],
|
||||
['link3', OrmEntity::BELONGS_TO],
|
||||
]
|
||||
);
|
||||
|
||||
$this->entity
|
||||
->expects($this->any())
|
||||
->method('getAttributeParam')
|
||||
->willReturnMap(
|
||||
|
||||
[
|
||||
['test4', 'relation', 'link4'],
|
||||
]
|
||||
|
||||
);
|
||||
|
||||
$this->scanner->apply($this->queryBuilder, $item);
|
||||
}
|
||||
|
||||
public function testHasRelatedMany(): void
|
||||
{
|
||||
$em = $this->createMock(EntityManager::class);
|
||||
$entity = $this->createMock(Entity::class);
|
||||
|
||||
$em->expects($this->once())
|
||||
->method('getNewEntity')
|
||||
->willReturn($entity);
|
||||
|
||||
$entity
|
||||
->expects($this->any())
|
||||
->method('hasRelation')
|
||||
->willReturnMap(
|
||||
[
|
||||
['link2', true],
|
||||
['link3', true],
|
||||
]
|
||||
);
|
||||
|
||||
$entity
|
||||
->expects($this->any())
|
||||
->method('getRelationType')
|
||||
->willReturnMap(
|
||||
[
|
||||
['link2', RelationType::HAS_MANY],
|
||||
['link3', RelationType::BELONGS_TO],
|
||||
]
|
||||
);
|
||||
|
||||
$scanner = new Scanner($em);
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'test1',
|
||||
'value' => 'value',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'TEST:(link2.test2)',
|
||||
'value' => 'value',
|
||||
],
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'link3.test3',
|
||||
'value' => 'value',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertTrue($scanner->hasRelatedMany('Test', $item));
|
||||
|
||||
$item = Item::fromRaw([
|
||||
'type' => 'and',
|
||||
'value' => [
|
||||
[
|
||||
'type' => 'equals',
|
||||
'attribute' => 'link3.test3',
|
||||
'value' => 'value',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertFalse($scanner->hasRelatedMany('Test', $item));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user