mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-27 15:10:28 +01:00
186 lines
5.8 KiB
PHP
186 lines
5.8 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace Xentral\Modules\Api\Resource\Feature;
|
||
|
|
||
|
use Xentral\Modules\Api\Exception\InvalidArgumentException;
|
||
|
use Xentral\Modules\Api\Exception\ResourceNotFoundException;
|
||
|
use Xentral\Modules\Api\Resource\AbstractResource;
|
||
|
|
||
|
trait IncludeFeatureTrait
|
||
|
{
|
||
|
/** @var array $includeSettings */
|
||
|
private $includeSettings;
|
||
|
|
||
|
/**
|
||
|
* @example in configure-Methode der Resource:
|
||
|
* $this->registerIncludes([
|
||
|
* 'projekte' => [
|
||
|
* 'key' => 'projekt',
|
||
|
* 'resource' => ProjectResource::class,
|
||
|
* 'columns' => [
|
||
|
* 'p.id',
|
||
|
* 'p.name',
|
||
|
* 'p.abkuerzung',
|
||
|
* 'p.beschreibung',
|
||
|
* 'p.farbe',
|
||
|
* ],
|
||
|
* ],
|
||
|
* ]);
|
||
|
*
|
||
|
* @param array $includes
|
||
|
*/
|
||
|
protected function registerIncludes($includes)
|
||
|
{
|
||
|
$this->includeSettings = $includes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $includes
|
||
|
* @param array $items
|
||
|
* @param bool $isCollection true=Mehrzeilig, false=Assoziatives Array
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function integrateIncludes(array $includes, array &$items, $isCollection = true)
|
||
|
{
|
||
|
// Keine Includes gesetzt
|
||
|
if (empty($includes)) {
|
||
|
return $items;
|
||
|
}
|
||
|
if (empty($this->includeSettings)) {
|
||
|
return $items;
|
||
|
}
|
||
|
|
||
|
// Doppelte Includes entfernen
|
||
|
$includes = array_unique($includes);
|
||
|
|
||
|
// Einzelnes Item in Collection verwandeln
|
||
|
if (!$isCollection) {
|
||
|
$items = [$items];
|
||
|
}
|
||
|
|
||
|
foreach ($includes as $includeName) {
|
||
|
|
||
|
if (empty($includeName)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$settings = $this->getIncludeSetting($includeName);
|
||
|
$subKey = $settings['key'];
|
||
|
|
||
|
if (empty($subKey)) {
|
||
|
throw new \RuntimeException(sprintf(
|
||
|
'Include "%s" not posible. Key is missing.', $includeName
|
||
|
));
|
||
|
}
|
||
|
|
||
|
// Nur bestimmte Spalten inkludieren?
|
||
|
$columns = isset($settings['columns']) ? $settings['columns'] : [];
|
||
|
|
||
|
// 1:n Beziehung zwischen Resource und Subresource
|
||
|
if (isset($settings['filter'])) {
|
||
|
|
||
|
/** @var AbstractResource $subResource */
|
||
|
$subResource = $this->getResource($settings['resource']);
|
||
|
|
||
|
foreach ($items as &$item) {
|
||
|
|
||
|
// Filter aufbereiten
|
||
|
$filter = $settings['filter'];
|
||
|
foreach ($filter as &$filterItem) {
|
||
|
// Filter benötigt Wert aus Haupt-Resource
|
||
|
if (strpos($filterItem['value'], ':') === 0) {
|
||
|
$key = substr_replace($filterItem['value'], '', 0, 1);
|
||
|
$filterItem['value'] = $item[$key];
|
||
|
}
|
||
|
}
|
||
|
unset($filterItem);
|
||
|
$filter = ['filter' => $filter]; // In ComplexSearch-Filter wandeln
|
||
|
|
||
|
// Sortierung vorhanden?
|
||
|
$sort = !empty($settings['sort']) ? $settings['sort'] : [];
|
||
|
|
||
|
try {
|
||
|
/** @var AbstractResource $subResource */
|
||
|
$subResult = $subResource->getList($filter, $sort, $columns, [], 1, 1000);
|
||
|
$subItems = $subResult->getData();
|
||
|
} catch (ResourceNotFoundException $e) {
|
||
|
$subItems = [];
|
||
|
}
|
||
|
$item[$settings['key']] = $subItems;
|
||
|
}
|
||
|
unset($item);
|
||
|
|
||
|
// 1:1 Beziehung zwischen Resource und Subresource
|
||
|
} else {
|
||
|
|
||
|
// Prüfen ob Spalte zum Integrieren in Haupt-Ergebnis existiert
|
||
|
if (!$this->arrayColumnExists($items, $subKey)) {
|
||
|
throw new \RuntimeException(sprintf(
|
||
|
'Include "%s" not posible. Key "%s" is missing.', $includeName, $subKey
|
||
|
));
|
||
|
}
|
||
|
|
||
|
// Benötigte Subresourcen-IDs aus Haupt-Ergebnis holen
|
||
|
$subIds = array_unique(array_column($items, $subKey));
|
||
|
if (empty($subIds)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Subresourcen anhand der IDs laden
|
||
|
try {
|
||
|
/** @var AbstractResource $subResource */
|
||
|
$subResource = $this->getResource($settings['resource']);
|
||
|
$subResult = $subResource->getIds($subIds, $columns);
|
||
|
} catch (ResourceNotFoundException $e) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Gefundene Subresourcen in Haupt-Ergebnis einbinden
|
||
|
array_walk($items, function (&$item, $id, $subItems) use ($subKey) {
|
||
|
$subId = (int)$item[$subKey];
|
||
|
if (isset($subItems[$subId])) {
|
||
|
$item[$subKey] = $subItems[$subId];
|
||
|
}
|
||
|
}, $subResult->getData());
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!$isCollection) {
|
||
|
return $items[0];
|
||
|
}
|
||
|
|
||
|
return $items;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $includeName
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
private function getIncludeSetting($includeName)
|
||
|
{
|
||
|
if (!isset($this->includeSettings[$includeName])) {
|
||
|
throw new InvalidArgumentException(
|
||
|
sprintf('Include "%s" is not registered.', $includeName)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $this->includeSettings[$includeName];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $items
|
||
|
* @param string $keyName
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
private function arrayColumnExists(array $items, $keyName)
|
||
|
{
|
||
|
$row = current($items);
|
||
|
|
||
|
return array_key_exists($keyName, $row);
|
||
|
}
|
||
|
}
|