formula find many

This commit is contained in:
Yuri Kuznetsov
2023-06-30 11:10:24 +03:00
parent 6de98fd652
commit ea4790eb6f
4 changed files with 196 additions and 2 deletions

View File

@@ -30,7 +30,7 @@
namespace Espo\Core\Formula\Exceptions;
/**
* Too few function arguments passsed.
* Too few function arguments passed.
*/
class TooFewArguments extends Error
{

View File

@@ -0,0 +1,146 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\RecordGroup;
use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Formula\EvaluatedArgumentList;
use Espo\Core\Formula\Exceptions\BadArgumentType;
use Espo\Core\Formula\Exceptions\Error as FormulaError;
use Espo\Core\Formula\Exceptions\TooFewArguments;
use Espo\Core\Formula\Func;
use Espo\Core\Select\SelectBuilderFactory;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
use Espo\ORM\Query\Part\Order;
class FindManyType implements Func
{
public function __construct(
private EntityManager $entityManager,
private SelectBuilderFactory $selectBuilderFactory
) {}
/**
* @return string[]
* @inheritDoc
*/
public function process(EvaluatedArgumentList $arguments): array
{
if (count($arguments) < 4) {
throw TooFewArguments::create(4);
}
$entityType = $arguments[0];
$limit = $arguments[1];
$orderBy = $arguments[2];
$order = $arguments[3] ?? Order::ASC;
if (!is_string($entityType)) {
throw BadArgumentType::create(1, 'string');
}
if (!is_int($limit)) {
throw BadArgumentType::create(2, 'int');
}
if ($orderBy !== null && !is_string($orderBy)) {
throw BadArgumentType::create(3, 'string|null');
}
if (!is_bool($order) && !is_string($orderBy)) {
throw BadArgumentType::create(4, 'string|bool');
}
$builder = $this->selectBuilderFactory
->create()
->from($entityType);
$whereClause = [];
if (count($arguments) <= 5) {
$filter = null;
if (count($arguments) === 5) {
$filter = $arguments[4];
}
if ($filter && !is_string($filter)) {
throw BadArgumentType::create(5, 'string');
}
if ($filter) {
$builder->withPrimaryFilter($filter);
}
}
else {
$i = 4;
while ($i < count($arguments) - 1) {
$key = $arguments[$i];
$value = $arguments[$i + 1];
$whereClause[] = [$key => $value];
$i = $i + 2;
}
}
try {
$queryBuilder = $builder->buildQueryBuilder();
}
catch (BadRequest|Error|Forbidden $e) {
throw new FormulaError($e->getMessage(), $e->getCode(), $e);
}
if (!empty($whereClause)) {
$queryBuilder->where($whereClause);
}
if ($orderBy) {
$queryBuilder->order($orderBy, $order);
}
$queryBuilder
->select(['id'])
->limit(0, $limit);
$collection = $this->entityManager
->getRDBRepository($entityType)
->clone($queryBuilder->build())
->find();
return array_map(
fn (Entity $entity) => $entity->getId(),
iterator_to_array($collection)
);
}
}

View File

@@ -298,6 +298,11 @@
"insertText": "record\\findOne(ENTITY_TYPE, ORDER_BY, ORDER, KEY1, VALUE1, KEY2, VALUE2)",
"returnType": "string"
},
{
"name": "record\\findMany",
"insertText": "record\\findMany(ENTITY_TYPE, LIMIT, ORDER_BY, ORDER, KEY1, VALUE1, KEY2, VALUE2)",
"returnType": "string"
},
{
"name": "record\\findRelatedOne",
"insertText": "record\\findRelatedOne(ENTITY_TYPE, ID, LINK, ORDER_BY, ORDER, KEY1, VALUE1, KEY2, VALUE2)",

View File

@@ -203,7 +203,7 @@ class FormulaTest extends \tests\integration\Core\BaseTestCase
$fm = $this->getContainer()->get('formulaManager');
$em = $this->getContainer()->get('entityManager');
$m1 =$em->createEntity('Meeting', [
$m1 = $em->createEntity('Meeting', [
'name' => '1',
'status' => 'Held',
]);
@@ -246,6 +246,49 @@ class FormulaTest extends \tests\integration\Core\BaseTestCase
$this->assertEquals(null, $result);
}
public function testFindMany(): void
{
$fm = $this->getContainer()->getByClass(Manager::class);
$em = $this->getContainer()->getByClass(EntityManager::class);
$m1 = $em->createEntity('Meeting', [
'name' => '1',
'status' => 'Held',
]);
$m2 = $em->createEntity('Meeting', [
'name' => '2',
'status' => 'Planned',
]);
$m3 = $em->createEntity('Meeting', [
'name' => '3',
'status' => 'Held',
]);
$m4 = $em->createEntity('Meeting', [
'name' => '4',
'status' => 'Planned',
'assignedUserId' => '1',
]);
$script = "record\\findMany('Meeting', 2, 'name', null, 'status=', 'Held')";
$result = $fm->run($script);
$this->assertEquals([$m1->getId(), $m3->getId()], $result);
$script = "record\\findMany('Meeting', 2, 'name', true, 'status=', 'Held')";
$result = $fm->run($script);
$this->assertEquals([$m3->getId(), $m1->getId()], $result);
$script = "record\\findMany('Meeting', 1, 'name', 'desc', 'status=', 'Held')";
$result = $fm->run($script);
$this->assertEquals([$m3->getId()], $result);
$script = "record\\findMany('Meeting', 2, 'name', 'ASC', 'planned')";
$result = $fm->run($script);
$this->assertEquals([$m2->getId(), $m4->getId()], $result);
}
public function testRecordFindRelatedOne1()
{
$fm = $this->getContainer()->get('formulaManager');