mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-12 19:21:33 +00:00
The official image from streamline does not currently work for the arm64 platform. As a temporary measure, the source code and docker build scripts have been lifted from the official images and are used to build locally. Some additional modifications are made to reduce overall image size, these are documented in docker/README.md
244 lines
10 KiB
PHP
244 lines
10 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\Component\VarDumper\Cloner;
|
|
|
|
/**
|
|
* @author Nicolas Grekas <p@tchwork.com>
|
|
*/
|
|
class VarCloner extends AbstractCloner
|
|
{
|
|
private static array $arrayCache = [];
|
|
|
|
protected function doClone(mixed $var): array
|
|
{
|
|
$len = 1; // Length of $queue
|
|
$pos = 0; // Number of cloned items past the minimum depth
|
|
$refsCounter = 0; // Hard references counter
|
|
$queue = [[$var]]; // This breadth-first queue is the return value
|
|
$hardRefs = []; // Map of original zval ids to stub objects
|
|
$objRefs = []; // Map of original object handles to their stub object counterpart
|
|
$objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning
|
|
$resRefs = []; // Map of original resource handles to their stub object counterpart
|
|
$values = []; // Map of stub objects' ids to original values
|
|
$maxItems = $this->maxItems;
|
|
$maxString = $this->maxString;
|
|
$minDepth = $this->minDepth;
|
|
$currentDepth = 0; // Current tree depth
|
|
$currentDepthFinalIndex = 0; // Final $queue index for current tree depth
|
|
$minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached
|
|
$cookie = (object) []; // Unique object used to detect hard references
|
|
$a = null; // Array cast for nested structures
|
|
$stub = null; // Stub capturing the main properties of an original item value
|
|
// or null if the original value is used directly
|
|
|
|
$arrayStub = new Stub();
|
|
$arrayStub->type = Stub::TYPE_ARRAY;
|
|
$fromObjCast = false;
|
|
|
|
for ($i = 0; $i < $len; ++$i) {
|
|
// Detect when we move on to the next tree depth
|
|
if ($i > $currentDepthFinalIndex) {
|
|
++$currentDepth;
|
|
$currentDepthFinalIndex = $len - 1;
|
|
if ($currentDepth >= $minDepth) {
|
|
$minimumDepthReached = true;
|
|
}
|
|
}
|
|
|
|
$refs = $vals = $queue[$i];
|
|
foreach ($vals as $k => $v) {
|
|
// $v is the original value or a stub object in case of hard references
|
|
|
|
$zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null;
|
|
|
|
if ($zvalRef) {
|
|
$vals[$k] = &$stub; // Break hard references to make $queue completely
|
|
unset($stub); // independent from the original structure
|
|
if (null !== $vals[$k] = $hardRefs[$zvalRef] ?? null) {
|
|
$v = $vals[$k];
|
|
if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
|
|
++$v->value->refCount;
|
|
}
|
|
++$v->refCount;
|
|
continue;
|
|
}
|
|
$vals[$k] = new Stub();
|
|
$vals[$k]->value = $v;
|
|
$vals[$k]->handle = ++$refsCounter;
|
|
$hardRefs[$zvalRef] = $vals[$k];
|
|
}
|
|
// Create $stub when the original value $v cannot be used directly
|
|
// If $v is a nested structure, put that structure in array $a
|
|
switch (true) {
|
|
case null === $v:
|
|
case \is_bool($v):
|
|
case \is_int($v):
|
|
case \is_float($v):
|
|
continue 2;
|
|
case \is_string($v):
|
|
if ('' === $v) {
|
|
continue 2;
|
|
}
|
|
if (!preg_match('//u', $v)) {
|
|
$stub = new Stub();
|
|
$stub->type = Stub::TYPE_STRING;
|
|
$stub->class = Stub::STRING_BINARY;
|
|
if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) {
|
|
$stub->cut = $cut;
|
|
$stub->value = substr($v, 0, -$cut);
|
|
} else {
|
|
$stub->value = $v;
|
|
}
|
|
} elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {
|
|
$stub = new Stub();
|
|
$stub->type = Stub::TYPE_STRING;
|
|
$stub->class = Stub::STRING_UTF8;
|
|
$stub->cut = $cut;
|
|
$stub->value = mb_substr($v, 0, $maxString, 'UTF-8');
|
|
} else {
|
|
continue 2;
|
|
}
|
|
$a = null;
|
|
break;
|
|
|
|
case \is_array($v):
|
|
if (!$v) {
|
|
continue 2;
|
|
}
|
|
$stub = $arrayStub;
|
|
|
|
$stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC;
|
|
$a = $v;
|
|
break;
|
|
|
|
case \is_object($v):
|
|
if (empty($objRefs[$h = spl_object_id($v)])) {
|
|
$stub = new Stub();
|
|
$stub->type = Stub::TYPE_OBJECT;
|
|
$stub->class = $v::class;
|
|
$stub->value = $v;
|
|
$stub->handle = $h;
|
|
$a = $this->castObject($stub, 0 < $i);
|
|
if ($v !== $stub->value) {
|
|
if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {
|
|
break;
|
|
}
|
|
$stub->handle = $h = spl_object_id($stub->value);
|
|
}
|
|
$stub->value = null;
|
|
if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
|
|
$stub->cut = \count($a);
|
|
$a = null;
|
|
}
|
|
}
|
|
if (empty($objRefs[$h])) {
|
|
$objRefs[$h] = $stub;
|
|
$objects[] = $v;
|
|
} else {
|
|
$stub = $objRefs[$h];
|
|
++$stub->refCount;
|
|
$a = null;
|
|
}
|
|
break;
|
|
|
|
default: // resource
|
|
if (empty($resRefs[$h = (int) $v])) {
|
|
$stub = new Stub();
|
|
$stub->type = Stub::TYPE_RESOURCE;
|
|
if ('Unknown' === $stub->class = @get_resource_type($v)) {
|
|
$stub->class = 'Closed';
|
|
}
|
|
$stub->value = $v;
|
|
$stub->handle = $h;
|
|
$a = $this->castResource($stub, 0 < $i);
|
|
$stub->value = null;
|
|
if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
|
|
$stub->cut = \count($a);
|
|
$a = null;
|
|
}
|
|
}
|
|
if (empty($resRefs[$h])) {
|
|
$resRefs[$h] = $stub;
|
|
} else {
|
|
$stub = $resRefs[$h];
|
|
++$stub->refCount;
|
|
$a = null;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ($a) {
|
|
if (!$minimumDepthReached || 0 > $maxItems) {
|
|
$queue[$len] = $a;
|
|
$stub->position = $len++;
|
|
} elseif ($pos < $maxItems) {
|
|
if ($maxItems < $pos += \count($a)) {
|
|
$a = \array_slice($a, 0, $maxItems - $pos, true);
|
|
if ($stub->cut >= 0) {
|
|
$stub->cut += $pos - $maxItems;
|
|
}
|
|
}
|
|
$queue[$len] = $a;
|
|
$stub->position = $len++;
|
|
} elseif ($stub->cut >= 0) {
|
|
$stub->cut += \count($a);
|
|
$stub->position = 0;
|
|
}
|
|
}
|
|
|
|
if ($arrayStub === $stub) {
|
|
if ($arrayStub->cut) {
|
|
$stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position];
|
|
$arrayStub->cut = 0;
|
|
} elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) {
|
|
$stub = self::$arrayCache[$arrayStub->class][$arrayStub->position];
|
|
} else {
|
|
self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position];
|
|
}
|
|
}
|
|
|
|
if (!$zvalRef) {
|
|
$vals[$k] = $stub;
|
|
} else {
|
|
$hardRefs[$zvalRef]->value = $stub;
|
|
}
|
|
}
|
|
|
|
if ($fromObjCast) {
|
|
$fromObjCast = false;
|
|
$refs = $vals;
|
|
$vals = [];
|
|
$j = -1;
|
|
foreach ($queue[$i] as $k => $v) {
|
|
foreach ([$k => true] as $gk => $gv) {
|
|
}
|
|
if ($gk !== $k) {
|
|
$vals = (object) $vals;
|
|
$vals->{$k} = $refs[++$j];
|
|
$vals = (array) $vals;
|
|
} else {
|
|
$vals[$k] = $refs[++$j];
|
|
}
|
|
}
|
|
}
|
|
|
|
$queue[$i] = $vals;
|
|
}
|
|
|
|
foreach ($values as $h => $v) {
|
|
$hardRefs[$h] = $v;
|
|
}
|
|
|
|
return $queue;
|
|
}
|
|
}
|