You need to sign in or sign up before continuing.
Select Git revision
EntityServiceFactory.php
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
AxiosExtractor.php 4.58 KiB
<?php
namespace UnicaenVue\Axios;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Query;
class AxiosExtractor
{
public static $loopControl = 50;
const DATETIME_FORMAT = 'Y-m-d\TH:i:s.u\Z'; // timestamp ISO 8601 pour HTML5
protected array $triggers = [];
public static function extract($data, array $properties = [], array $triggers = [])
{
$axios = new self;
$axios->triggers = $triggers;
return $axios->extractData($data, $properties);
}
protected function extractData($data, array $properties = [], string $path = '')
{
$triggerPath = $path ? $path : '/';
if ($data instanceof Query) {
$result = $this->extractData($data->getResult(), $properties, '');
} elseif ($this->isList($data)) {
$result = $this->extractList($data, $properties, $path);
$triggerPath .= '[]';
} elseif (is_array($data)) {
$result = $this->extractArray($data, $properties, $path);
} elseif ($data instanceof \DateTime) {
$result = $data->format(self::DATETIME_FORMAT);
} elseif (is_object($data)) {
$result = $this->extractObject($data, $properties, $path);
} else {
$result = $data;
}
if (array_key_exists($triggerPath, $this->triggers) && !$data instanceof Query) {
// trigger est un callable qui accepte deux arguments : le premier les la donnée originale, le second la donnée extraite
// il doit retourner une donnée qui remplacera la donnée extraite
$result = $this->triggers[$triggerPath]($data, $result);
}
return $result;
}
protected function extractObject($data, array $properties, string $path = ''): array
{
// contrôle de boucle récursive, afin de ne pas saturer la mémoire...
if (substr_count($path, '/') >= self::$loopControl) {
//return [];
throw new \Exception("AxiosExtractor has detected a possible infinite loop, and aborted your script with a stack depth of '" . self::$loopControl . "' frames");
}
$result = [];
if (empty($properties) && $data instanceof AxiosExtractorInterface) {
$properties = $data->axiosDefinition();
}
foreach ($properties as $property) {
if (is_array($property)) {
$subProperties = $property[1];
$property = $property[0];
} else {
$subProperties = [];
}
$methods = [
$property,
'get' . ucfirst($property),
'is' . ucfirst($property),
'has' . ucfirst($property),
];
foreach ($methods as $method) {
if (method_exists($data, $method)) {
$value = $data->$method();
$result[$property] = $this->extractData($value, $subProperties, $path . '/' . $property);
break;
}
}
}
return $result;
}
protected function extractArray(array $data, array $properties, string $path = ''): array
{
$result = [];
if (empty($properties)) {
$properties = array_keys($data);
}
foreach ($properties as $property) {
if (is_array($property)) {
$subProperties = $property[1];
$property = $property[0];
} else {
$subProperties = [];
}
if (array_key_exists($property, $data)) {
$result[$property] = $this->extractData($data[$property], $subProperties, $path . '/' . $property);
}
}
return $result;
}
protected function extractList($list, array $properties = [], string $path = ''): array
{
$result = [];
foreach ($list as $index => $sobj) {
$result[$index] = $this->extractData($sobj, $properties, $path);
}
return $result;
}
protected function isList($data): bool
{
if ($data instanceof Collection) {
return true;
}
if (!is_array($data)) {
return false;
}
foreach ($data as $k => $v) {
if (!is_numeric($k)) {
// une clé non numérique est rejetée
return false;
}
if (!(is_array($v) || is_object($v))) {
// une liste doit être une liste d'objets ou bien une liste de tableaux
return false;
}
}
return true;
}
}