Initial commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Core\ORM;
|
||||
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Creates entities with custom defs. Need for supporting foreign fields like `linkName.attribute`.
|
||||
*
|
||||
* Not used as of Espo v9.1.7.
|
||||
*/
|
||||
class CustomEntityFactory
|
||||
{
|
||||
public function __construct(
|
||||
private InjectableFactory $injectableFactory,
|
||||
private EntityManager $entityManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string, mixed>> $attributeDefs
|
||||
*/
|
||||
public function create(string $entityType, array $attributeDefs): Entity
|
||||
{
|
||||
return $this->createImplementation($entityType, $attributeDefs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string, mixed>> $attributeDefs
|
||||
*/
|
||||
private function createImplementation(string $entityType, array $attributeDefs): Entity
|
||||
{
|
||||
$seed = $this->entityManager->getEntityFactory()->create($entityType);
|
||||
|
||||
$className = get_class($seed);
|
||||
|
||||
$defs = $this->entityManager->getMetadata()->get($entityType);
|
||||
|
||||
$defs['attributes'] = array_merge($defs['attributes'], $attributeDefs);
|
||||
|
||||
$entity = $this->injectableFactory->createWith($className, [
|
||||
'entityType' => $entityType,
|
||||
'defs' => $defs,
|
||||
'valueAccessorFactory' => null,
|
||||
]);
|
||||
|
||||
if (!$entity instanceof Entity) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
174
custom/Espo/Modules/Advanced/Core/ORM/SthCollection.php
Normal file
174
custom/Espo/Modules/Advanced/Core/ORM/SthCollection.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Core\ORM;
|
||||
|
||||
use Espo\Core\FieldProcessing\ListLoadProcessor;
|
||||
use Espo\Core\FieldProcessing\Loader\Params as LoaderParams;
|
||||
use Espo\Core\ORM\Entity as CoreEntity;
|
||||
use Espo\Core\ORM\EntityFactory;
|
||||
use Espo\ORM\Collection;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use PDOStatement;
|
||||
use PDO;
|
||||
use IteratorAggregate;
|
||||
use stdClass;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* @implements IteratorAggregate<int, Entity>
|
||||
* @implements Collection<Entity>
|
||||
*/
|
||||
class SthCollection implements IteratorAggregate, Collection
|
||||
{
|
||||
/**
|
||||
* @param array<string, array<string, mixed>> $attributeDefs Additional attributes.
|
||||
* @param string[] $linkMultipleFieldList
|
||||
* @param object{entityType: string, name: string}[] $foreignLinkFieldDataList
|
||||
*/
|
||||
public function __construct(
|
||||
private PDOStatement $sth,
|
||||
private string $entityType,
|
||||
private EntityManager $entityManager,
|
||||
private $attributeDefs,
|
||||
private $linkMultipleFieldList,
|
||||
private $foreignLinkFieldDataList,
|
||||
private CustomEntityFactory $customEntityFactory,
|
||||
private ListLoadProcessor $listLoadProcessor,
|
||||
) {}
|
||||
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return (function () {
|
||||
while ($row = $this->sth->fetch(PDO::FETCH_ASSOC)) {
|
||||
$rowData = [];
|
||||
|
||||
foreach ($row as $key => $value) {
|
||||
/** @var string $attribute */
|
||||
$attribute = str_replace('.', '_', $key);
|
||||
|
||||
$rowData[$attribute] = $value;
|
||||
}
|
||||
|
||||
$select = array_keys($rowData);
|
||||
|
||||
foreach ($this->linkMultipleFieldList as $it) {
|
||||
$select[] = $it . 'Ids';
|
||||
$select[] = $it . 'Names';
|
||||
}
|
||||
|
||||
$entity = $this->prepareEntity();
|
||||
|
||||
$entity->set($rowData);
|
||||
$entity->setAsFetched();
|
||||
|
||||
$fieldLoaderParams = LoaderParams::create()->withSelect($select);
|
||||
|
||||
$this->listLoadProcessor->process($entity, $fieldLoaderParams);
|
||||
|
||||
$this->loadNoLoadLinkMultiple($entity);
|
||||
|
||||
foreach ($this->foreignLinkFieldDataList as $item) {
|
||||
$foreignId = $entity->get($item->name . 'Id');
|
||||
|
||||
if (!$foreignId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$foreignEntity = $this->entityManager
|
||||
->getRDBRepository($item->entityType)
|
||||
->where(['id' => $foreignId])
|
||||
->select(['name'])
|
||||
->findOne();
|
||||
|
||||
if (!$foreignEntity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$entity->set($item->name . 'Name', $foreignEntity->get('name'));
|
||||
}
|
||||
|
||||
$entity->setAsFetched();
|
||||
|
||||
yield $entity;
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return stdClass[]
|
||||
*/
|
||||
public function getValueMapList(): array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ($this as $entity) {
|
||||
$list[] = $entity->getValueMap();
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
private function prepareEntity(): Entity
|
||||
{
|
||||
$factory = $this->entityManager->getEntityFactory();
|
||||
|
||||
/** @noinspection PhpConditionAlreadyCheckedInspection */
|
||||
if (
|
||||
$factory instanceof EntityFactory &&
|
||||
/** @phpstan-ignore-next-line function.alreadyNarrowedType */
|
||||
method_exists($factory, 'createWithAdditionalAttributes')
|
||||
) {
|
||||
/** @noinspection PhpInternalEntityUsedInspection */
|
||||
return $factory->createWithAdditionalAttributes($this->entityType, $this->attributeDefs);
|
||||
}
|
||||
|
||||
// Before Espo v9.1.7.
|
||||
return $this->customEntityFactory->create($this->entityType, $this->attributeDefs);
|
||||
}
|
||||
|
||||
private function loadNoLoadLinkMultiple(Entity $entity): void
|
||||
{
|
||||
$entityDefs = $this->entityManager->getDefs()->getEntity($this->entityType);
|
||||
|
||||
if (!$entity instanceof CoreEntity) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->linkMultipleFieldList as $field) {
|
||||
$fieldDefs = $entityDefs->tryGetField($field);
|
||||
|
||||
if (!$fieldDefs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$fieldDefs->getParam('noLoad')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$entity->hasLinkMultipleField($field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @noinspection PhpInternalEntityUsedInspection */
|
||||
$entity->loadLinkMultipleField($field);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user