Spaces:
No application file
No application file
File size: 4,644 Bytes
d2897cd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
<?php
namespace Mautic\ApiBundle\Helper;
class BatchIdToEntityHelper
{
/**
* @var array
*/
private $ids = [];
private array $originalKeys = [];
private array $errors = [];
private bool $isAssociative = false;
/**
* @param string $idKey
*/
public function __construct(
array $parameters,
private $idKey = 'id'
) {
$this->extractIds($parameters);
}
public function hasIds(): bool
{
return !empty($this->ids);
}
/**
* @return array
*/
public function getIds()
{
return $this->ids;
}
public function hasErrors(): bool
{
return !empty($this->errors);
}
/**
* @return array
*/
public function getErrors()
{
return $this->errors;
}
/**
* Reorder the entities based on the original keys
* BC allowed a request to have associative keys (don't ask why; yes it's terrible implementation but we're keeping BC here)
* The issue this solves is the response should match the format given by the request. If the request had associative keys, the response
* will return with associative keys (json object). If the request was a sequential numeric array starting with 0, the response will
* be a simple array (json array).
*/
public function orderByOriginalKey(array $entities): array
{
if (!$this->isAssociative) {
// The request was keyed by sequential numbers starting with 0
return array_values($entities);
}
// Ensure entities are keyed by ID in order to find the original keys assuming that some entities are missing if the ID was not found
$entitiesKeyedById = [];
foreach ($entities as $entity) {
$entitiesKeyedById[$entity->getId()] = $entity;
}
$orderedEntities = [];
foreach ($this->ids as $key => $id) {
if (!isset($entitiesKeyedById[$id])) {
continue;
}
$originalKey = $this->originalKeys[$key];
$orderedEntities[$originalKey] = $entitiesKeyedById[$id];
}
return $orderedEntities;
}
private function extractIds(array $parameters): void
{
$this->ids = [];
if (isset($parameters['ids'])) {
$this->extractIdsFromIdKey($parameters['ids']);
return;
}
$this->extractIdsFromParams($parameters);
}
/**
* @param mixed $ids
*/
private function extractIdsFromIdKey($ids): void
{
// ['ids' => [1,2,3]]
if (is_array($ids)) {
$this->isAssociative = $this->isAssociativeArray($ids);
$this->ids = array_values($ids);
$this->originalKeys = array_keys($ids);
return;
}
// ['ids' => '1,2,3'] OR ['ids' => '1']
if (str_contains($ids, ',') || is_numeric($ids)) {
$this->ids = str_getcsv($ids);
$this->originalKeys = array_keys($this->ids);
$this->isAssociative = false;
return;
}
// Couldn't parse the 'ids' key; not throwing an exception in order to keep BC with
// the old CommonApiController code and the use of a foreach in extractIdsFromParams
$this->errors[] = 'mautic.api.call.id_missing';
}
private function extractIdsFromParams(array $parameters): void
{
$this->isAssociative = $this->isAssociativeArray($parameters);
$this->originalKeys = array_keys($parameters);
// [1,2,3]
$firstKey = array_key_first($parameters);
if (!is_array($parameters[$firstKey])) {
$this->ids = array_values($parameters);
return;
}
// [ ['id' => 1, 'foo' => 'bar'], ['id' => 2, 'bar' => 'foo'] ]
foreach ($parameters as $key => $params) {
// Missing id column key in the array; terrible but keep BC
if (!isset($params[$this->idKey])) {
$this->errors[$key] = 'mautic.api.call.id_missing';
continue;
}
$this->ids[] = $params[$this->idKey];
}
}
private function isAssociativeArray(array $array): bool
{
if (empty($array)) {
return false;
}
$firstKey = array_key_first($array);
return array_keys($array) !== range(0, count($array) - 1) && 0 !== $firstKey;
}
public function setIsAssociative(bool $isAssociative): void
{
$this->isAssociative = $isAssociative;
}
}
|