Initial commit: CloudOps infrastructure platform

This commit is contained in:
root
2026-04-09 19:58:57 +02:00
commit 1166a52f26
7762 changed files with 839452 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
<?php
namespace Mautic\ApiBundle\Helper;
use Mautic\CoreBundle\Helper\CsvHelper;
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])) {
$hasPreviousId = array_filter(
$entities,
fn ($entity) => $id == $entity->getPreviousId()
);
if ($hasPreviousId) {
$orderedEntities[$key] = array_shift($hasPreviousId);
}
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 = CsvHelper::strGetCsv($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;
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace Mautic\ApiBundle\Helper;
use Doctrine\ORM\Tools\Pagination\Paginator;
class EntityResultHelper
{
/**
* @param array<mixed>|Paginator<mixed> $results
* @param callable|null $callback
*
* @return array<mixed>|\ArrayObject<int,mixed>
*/
public function getArray($results, $callback = null)
{
$entities = [];
// we have to convert them from paginated proxy functions to entities in order for them to be
// returned by the serializer/rest bundle
foreach ($results as $key => $entityRow) {
$entities[$key] = $this->getEntityData($entityRow);
if (is_callable($callback)) {
$callback($entities[$key]);
}
}
// solving array/object discrepancy for empty values
if ($this->isKeyedById($results) && empty($entities)) {
$entities = new \ArrayObject();
}
return $entities;
}
/**
* @param mixed $entityRow
*
* @return mixed
*/
private function getEntityData($entityRow)
{
if (is_array($entityRow) && isset($entityRow[0])) {
return $this->getDataForArray($entityRow);
}
return $entityRow;
}
/**
* @param array $array
*
* @return mixed
*/
private function getDataForArray($array)
{
if (is_object($array[0])) {
return $this->getDataForObject($array);
}
return $array[0];
}
/**
* @param object $object
*
* @return mixed
*/
private function getDataForObject($object)
{
foreach ($object as $key => $value) {
if (0 === $key) {
continue;
}
$object[0]->$key = $value;
}
return $object[0];
}
/**
* @param array<mixed>|Paginator<mixed> $results
*/
private function isKeyedById($results): bool
{
return !$results instanceof Paginator;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Mautic\ApiBundle\Helper;
use Symfony\Component\HttpFoundation\Request;
class RequestHelper
{
public static function hasBasicAuth(Request $request): bool
{
return str_starts_with(strtolower((string) $request->headers->get('Authorization')), 'basic');
}
public static function isApiRequest(Request $request): bool
{
$requestUrl = $request->getRequestUri();
// Check if /oauth or /api
$isApiRequest = (str_contains($requestUrl, '/oauth') || str_contains($requestUrl, '/api'));
defined('MAUTIC_API_REQUEST') or define('MAUTIC_API_REQUEST', $isApiRequest);
return $isApiRequest;
}
}