Import latest app updates from streamline

An updated set of source files and initialization was provided by streamline to
address issues observed during initial testing. These files have been updated in
order to generate a new set of app images.
This commit is contained in:
2024-04-11 11:16:51 -07:00
parent cb4c6b4c1a
commit 4a89356390
10435 changed files with 107737 additions and 1220538 deletions
@@ -1,106 +0,0 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/global-state.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\GlobalState;
use const PHP_EOL;
use function is_array;
use function is_scalar;
use function serialize;
use function sprintf;
use function var_export;
final class CodeExporter
{
public function constants(Snapshot $snapshot): string
{
$result = '';
foreach ($snapshot->constants() as $name => $value) {
$result .= sprintf(
'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n",
$name,
$name,
$this->exportVariable($value)
);
}
return $result;
}
public function globalVariables(Snapshot $snapshot): string
{
$result = <<<'EOT'
call_user_func(
function ()
{
foreach (array_keys($GLOBALS) as $key) {
unset($GLOBALS[$key]);
}
}
);
EOT;
foreach ($snapshot->globalVariables() as $name => $value) {
$result .= sprintf(
'$GLOBALS[%s] = %s;' . PHP_EOL,
$this->exportVariable($name),
$this->exportVariable($value)
);
}
return $result;
}
public function iniSettings(Snapshot $snapshot): string
{
$result = '';
foreach ($snapshot->iniSettings() as $key => $value) {
$result .= sprintf(
'@ini_set(%s, %s);' . "\n",
$this->exportVariable($key),
$this->exportVariable($value)
);
}
return $result;
}
private function exportVariable(mixed $variable): string
{
if (is_scalar($variable) || null === $variable ||
(is_array($variable) && $this->arrayOnlyContainsScalars($variable))) {
return var_export($variable, true);
}
return 'unserialize(' . var_export(serialize($variable), true) . ')';
}
private function arrayOnlyContainsScalars(array $array): bool
{
$result = true;
foreach ($array as $element) {
if (is_array($element)) {
$result = $this->arrayOnlyContainsScalars($element);
} elseif (!is_scalar($element) && null !== $element) {
$result = false;
}
if ($result === false) {
break;
}
}
return $result;
}
}
@@ -1,95 +0,0 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/global-state.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\GlobalState;
use function in_array;
use function strpos;
use ReflectionClass;
final class ExcludeList
{
private array $globalVariables = [];
private array $classes = [];
private array $classNamePrefixes = [];
private array $parentClasses = [];
private array $interfaces = [];
private array $staticProperties = [];
public function addGlobalVariable(string $variableName): void
{
$this->globalVariables[$variableName] = true;
}
public function addClass(string $className): void
{
$this->classes[] = $className;
}
public function addSubclassesOf(string $className): void
{
$this->parentClasses[] = $className;
}
public function addImplementorsOf(string $interfaceName): void
{
$this->interfaces[] = $interfaceName;
}
public function addClassNamePrefix(string $classNamePrefix): void
{
$this->classNamePrefixes[] = $classNamePrefix;
}
public function addStaticProperty(string $className, string $propertyName): void
{
if (!isset($this->staticProperties[$className])) {
$this->staticProperties[$className] = [];
}
$this->staticProperties[$className][$propertyName] = true;
}
public function isGlobalVariableExcluded(string $variableName): bool
{
return isset($this->globalVariables[$variableName]);
}
/**
* @psalm-param class-string $className
*/
public function isStaticPropertyExcluded(string $className, string $propertyName): bool
{
if (in_array($className, $this->classes, true)) {
return true;
}
foreach ($this->classNamePrefixes as $prefix) {
if (strpos($className, $prefix) === 0) {
return true;
}
}
$class = new ReflectionClass($className);
foreach ($this->parentClasses as $type) {
if ($class->isSubclassOf($type)) {
return true;
}
}
foreach ($this->interfaces as $type) {
if ($class->implementsInterface($type)) {
return true;
}
}
return isset($this->staticProperties[$className][$propertyName]);
}
}
@@ -1,106 +0,0 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/global-state.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\GlobalState;
use function array_diff;
use function array_key_exists;
use function array_keys;
use function array_merge;
use function in_array;
use function is_array;
use ReflectionClass;
use ReflectionProperty;
final class Restorer
{
public function restoreGlobalVariables(Snapshot $snapshot): void
{
$superGlobalArrays = $snapshot->superGlobalArrays();
foreach ($superGlobalArrays as $superGlobalArray) {
$this->restoreSuperGlobalArray($snapshot, $superGlobalArray);
}
$globalVariables = $snapshot->globalVariables();
foreach (array_keys($GLOBALS) as $key) {
if ($key !== 'GLOBALS' &&
!in_array($key, $superGlobalArrays, true) &&
!$snapshot->excludeList()->isGlobalVariableExcluded($key)) {
if (array_key_exists($key, $globalVariables)) {
$GLOBALS[$key] = $globalVariables[$key];
} else {
unset($GLOBALS[$key]);
}
}
}
}
public function restoreStaticProperties(Snapshot $snapshot): void
{
$current = new Snapshot($snapshot->excludeList(), false, false, false, false, true, false, false, false, false);
$newClasses = array_diff($current->classes(), $snapshot->classes());
unset($current);
foreach ($snapshot->staticProperties() as $className => $staticProperties) {
foreach ($staticProperties as $name => $value) {
$reflector = new ReflectionProperty($className, $name);
$reflector->setValue(null, $value);
}
}
foreach ($newClasses as $className) {
$class = new ReflectionClass($className);
$defaults = $class->getDefaultProperties();
foreach ($class->getProperties() as $property) {
if (!$property->isStatic()) {
continue;
}
$name = $property->getName();
if ($snapshot->excludeList()->isStaticPropertyExcluded($className, $name)) {
continue;
}
if (!isset($defaults[$name])) {
continue;
}
$property->setValue(null, $defaults[$name]);
}
}
}
private function restoreSuperGlobalArray(Snapshot $snapshot, string $superGlobalArray): void
{
$superGlobalVariables = $snapshot->superGlobalVariables();
if (isset($GLOBALS[$superGlobalArray], $superGlobalVariables[$superGlobalArray]) &&
is_array($GLOBALS[$superGlobalArray])) {
$keys = array_keys(
array_merge(
$GLOBALS[$superGlobalArray],
$superGlobalVariables[$superGlobalArray]
)
);
foreach ($keys as $key) {
if (isset($superGlobalVariables[$superGlobalArray][$key])) {
$GLOBALS[$superGlobalArray][$key] = $superGlobalVariables[$superGlobalArray][$key];
} else {
unset($GLOBALS[$superGlobalArray][$key]);
}
}
}
}
}
@@ -1,371 +0,0 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/global-state.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\GlobalState;
use function array_keys;
use function array_merge;
use function array_reverse;
use function assert;
use function func_get_args;
use function get_declared_classes;
use function get_declared_interfaces;
use function get_declared_traits;
use function get_defined_constants;
use function get_defined_functions;
use function get_included_files;
use function in_array;
use function ini_get_all;
use function is_array;
use function is_object;
use function is_resource;
use function is_scalar;
use function serialize;
use function unserialize;
use ReflectionClass;
use SebastianBergmann\ObjectReflector\ObjectReflector;
use SebastianBergmann\RecursionContext\Context;
use Throwable;
/**
* A snapshot of global state.
*/
class Snapshot
{
private ExcludeList $excludeList;
private array $globalVariables = [];
private array $superGlobalArrays = [];
private array $superGlobalVariables = [];
private array $staticProperties = [];
private array $iniSettings = [];
private array $includedFiles = [];
private array $constants = [];
private array $functions = [];
private array $interfaces = [];
private array $classes = [];
private array $traits = [];
public function __construct(ExcludeList $excludeList = null, bool $includeGlobalVariables = true, bool $includeStaticProperties = true, bool $includeConstants = true, bool $includeFunctions = true, bool $includeClasses = true, bool $includeInterfaces = true, bool $includeTraits = true, bool $includeIniSettings = true, bool $includeIncludedFiles = true)
{
$this->excludeList = $excludeList ?: new ExcludeList;
if ($includeConstants) {
$this->snapshotConstants();
}
if ($includeFunctions) {
$this->snapshotFunctions();
}
if ($includeClasses || $includeStaticProperties) {
$this->snapshotClasses();
}
if ($includeInterfaces) {
$this->snapshotInterfaces();
}
if ($includeGlobalVariables) {
$this->setupSuperGlobalArrays();
$this->snapshotGlobals();
}
if ($includeStaticProperties) {
$this->snapshotStaticProperties();
}
if ($includeIniSettings) {
$this->iniSettings = ini_get_all(null, false);
}
if ($includeIncludedFiles) {
$this->includedFiles = get_included_files();
}
if ($includeTraits) {
$this->traits = get_declared_traits();
}
}
public function excludeList(): ExcludeList
{
return $this->excludeList;
}
public function globalVariables(): array
{
return $this->globalVariables;
}
public function superGlobalVariables(): array
{
return $this->superGlobalVariables;
}
public function superGlobalArrays(): array
{
return $this->superGlobalArrays;
}
public function staticProperties(): array
{
return $this->staticProperties;
}
public function iniSettings(): array
{
return $this->iniSettings;
}
public function includedFiles(): array
{
return $this->includedFiles;
}
public function constants(): array
{
return $this->constants;
}
public function functions(): array
{
return $this->functions;
}
public function interfaces(): array
{
return $this->interfaces;
}
public function classes(): array
{
return $this->classes;
}
public function traits(): array
{
return $this->traits;
}
private function snapshotConstants(): void
{
$constants = get_defined_constants(true);
if (isset($constants['user'])) {
$this->constants = $constants['user'];
}
}
private function snapshotFunctions(): void
{
$functions = get_defined_functions();
$this->functions = $functions['user'];
}
private function snapshotClasses(): void
{
foreach (array_reverse(get_declared_classes()) as $className) {
$class = new ReflectionClass($className);
if (!$class->isUserDefined()) {
break;
}
$this->classes[] = $className;
}
$this->classes = array_reverse($this->classes);
}
private function snapshotInterfaces(): void
{
foreach (array_reverse(get_declared_interfaces()) as $interfaceName) {
$class = new ReflectionClass($interfaceName);
if (!$class->isUserDefined()) {
break;
}
$this->interfaces[] = $interfaceName;
}
$this->interfaces = array_reverse($this->interfaces);
}
private function snapshotGlobals(): void
{
$superGlobalArrays = $this->superGlobalArrays();
foreach ($superGlobalArrays as $superGlobalArray) {
$this->snapshotSuperGlobalArray($superGlobalArray);
}
foreach (array_keys($GLOBALS) as $key) {
if ($key !== 'GLOBALS' &&
!in_array($key, $superGlobalArrays, true) &&
$this->canBeSerialized($GLOBALS[$key]) &&
!$this->excludeList->isGlobalVariableExcluded($key)) {
/* @noinspection UnserializeExploitsInspection */
$this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key]));
}
}
}
private function snapshotSuperGlobalArray(string $superGlobalArray): void
{
$this->superGlobalVariables[$superGlobalArray] = [];
if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) {
foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
/* @noinspection UnserializeExploitsInspection */
$this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value));
}
}
}
private function snapshotStaticProperties(): void
{
foreach ($this->classes as $className) {
$class = new ReflectionClass($className);
$snapshot = [];
foreach ($class->getProperties() as $property) {
if ($property->isStatic()) {
$name = $property->getName();
if ($this->excludeList->isStaticPropertyExcluded($className, $name)) {
continue;
}
if (!$property->isInitialized()) {
continue;
}
$value = $property->getValue();
if ($this->canBeSerialized($value)) {
/* @noinspection UnserializeExploitsInspection */
$snapshot[$name] = unserialize(serialize($value));
}
}
}
if (!empty($snapshot)) {
$this->staticProperties[$className] = $snapshot;
}
}
}
private function setupSuperGlobalArrays(): void
{
$this->superGlobalArrays = [
'_ENV',
'_POST',
'_GET',
'_COOKIE',
'_SERVER',
'_FILES',
'_REQUEST',
];
}
private function canBeSerialized(mixed $variable): bool
{
if (is_scalar($variable) || $variable === null) {
return true;
}
if (is_resource($variable)) {
return false;
}
foreach ($this->enumerateObjectsAndResources($variable) as $value) {
if (is_resource($value)) {
return false;
}
if (is_object($value)) {
$class = new ReflectionClass($value);
if ($class->isAnonymous()) {
return false;
}
try {
@serialize($value);
} catch (Throwable $t) {
return false;
}
}
}
return true;
}
private function enumerateObjectsAndResources(mixed $variable): array
{
if (isset(func_get_args()[1])) {
$processed = func_get_args()[1];
} else {
$processed = new Context;
}
assert($processed instanceof Context);
$result = [];
if ($processed->contains($variable)) {
return $result;
}
$array = $variable;
/* @noinspection UnusedFunctionResultInspection */
$processed->add($variable);
if (is_array($variable)) {
foreach ($array as $element) {
if (!is_array($element) && !is_object($element) && !is_resource($element)) {
continue;
}
if (!is_resource($element)) {
/** @noinspection SlowArrayOperationsInLoopInspection */
$result = array_merge(
$result,
$this->enumerateObjectsAndResources($element, $processed)
);
} else {
$result[] = $element;
}
}
} else {
$result[] = $variable;
foreach ((new ObjectReflector)->getProperties($variable) as $value) {
if (!is_array($value) && !is_object($value) && !is_resource($value)) {
continue;
}
if (!is_resource($value)) {
/** @noinspection SlowArrayOperationsInLoopInspection */
$result = array_merge(
$result,
$this->enumerateObjectsAndResources($value, $processed)
);
} else {
$result[] = $value;
}
}
}
return $result;
}
}
@@ -1,16 +0,0 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/global-state.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\GlobalState;
use Throwable;
interface Exception extends Throwable
{
}
@@ -1,14 +0,0 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/global-state.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\GlobalState;
final class RuntimeException extends \RuntimeException implements Exception
{
}