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,95 +0,0 @@
<?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\Mime\Part;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class AbstractMultipartPart extends AbstractPart
{
private ?string $boundary = null;
private array $parts = [];
public function __construct(AbstractPart ...$parts)
{
parent::__construct();
foreach ($parts as $part) {
$this->parts[] = $part;
}
}
/**
* @return AbstractPart[]
*/
public function getParts(): array
{
return $this->parts;
}
public function getMediaType(): string
{
return 'multipart';
}
public function getPreparedHeaders(): Headers
{
$headers = parent::getPreparedHeaders();
$headers->setHeaderParameter('Content-Type', 'boundary', $this->getBoundary());
return $headers;
}
public function bodyToString(): string
{
$parts = $this->getParts();
$string = '';
foreach ($parts as $part) {
$string .= '--'.$this->getBoundary()."\r\n".$part->toString()."\r\n";
}
$string .= '--'.$this->getBoundary()."--\r\n";
return $string;
}
public function bodyToIterable(): iterable
{
$parts = $this->getParts();
foreach ($parts as $part) {
yield '--'.$this->getBoundary()."\r\n";
yield from $part->toIterable();
yield "\r\n";
}
yield '--'.$this->getBoundary()."--\r\n";
}
public function asDebugString(): string
{
$str = parent::asDebugString();
foreach ($this->getParts() as $part) {
$lines = explode("\n", $part->asDebugString());
$str .= "\n".array_shift($lines);
foreach ($lines as $line) {
$str .= "\n |".$line;
}
}
return $str;
}
private function getBoundary(): string
{
return $this->boundary ??= strtr(base64_encode(random_bytes(6)), '+/', '-_');
}
}
@@ -1,65 +0,0 @@
<?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\Mime\Part;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class AbstractPart
{
private Headers $headers;
public function __construct()
{
$this->headers = new Headers();
}
public function getHeaders(): Headers
{
return $this->headers;
}
public function getPreparedHeaders(): Headers
{
$headers = clone $this->headers;
$headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype());
return $headers;
}
public function toString(): string
{
return $this->getPreparedHeaders()->toString()."\r\n".$this->bodyToString();
}
public function toIterable(): iterable
{
yield $this->getPreparedHeaders()->toString();
yield "\r\n";
yield from $this->bodyToIterable();
}
public function asDebugString(): string
{
return $this->getMediaType().'/'.$this->getMediaSubtype();
}
abstract public function bodyToString(): string;
abstract public function bodyToIterable(): iterable;
abstract public function getMediaType(): string;
abstract public function getMediaSubtype(): string;
}
@@ -1,168 +0,0 @@
<?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\Mime\Part;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class DataPart extends TextPart
{
/** @internal */
protected array $_parent;
private ?string $filename = null;
private string $mediaType;
private ?string $cid = null;
/**
* @param resource|string|File $body Use a File instance to defer loading the file until rendering
*/
public function __construct($body, ?string $filename = null, ?string $contentType = null, ?string $encoding = null)
{
if ($body instanceof File && !$filename) {
$filename = $body->getFilename();
}
$contentType ??= $body instanceof File ? $body->getContentType() : 'application/octet-stream';
[$this->mediaType, $subtype] = explode('/', $contentType);
parent::__construct($body, null, $subtype, $encoding);
if (null !== $filename) {
$this->filename = $filename;
$this->setName($filename);
}
$this->setDisposition('attachment');
}
public static function fromPath(string $path, ?string $name = null, ?string $contentType = null): self
{
return new self(new File($path), $name, $contentType);
}
/**
* @return $this
*/
public function asInline(): static
{
return $this->setDisposition('inline');
}
/**
* @return $this
*/
public function setContentId(string $cid): static
{
if (!str_contains($cid, '@')) {
throw new InvalidArgumentException(sprintf('Invalid cid "%s".', $cid));
}
$this->cid = $cid;
return $this;
}
public function getContentId(): string
{
return $this->cid ?: $this->cid = $this->generateContentId();
}
public function hasContentId(): bool
{
return null !== $this->cid;
}
public function getMediaType(): string
{
return $this->mediaType;
}
public function getPreparedHeaders(): Headers
{
$headers = parent::getPreparedHeaders();
if (null !== $this->cid) {
$headers->setHeaderBody('Id', 'Content-ID', $this->cid);
}
if (null !== $this->filename) {
$headers->setHeaderParameter('Content-Disposition', 'filename', $this->filename);
}
return $headers;
}
public function asDebugString(): string
{
$str = parent::asDebugString();
if (null !== $this->filename) {
$str .= ' filename: '.$this->filename;
}
return $str;
}
public function getFilename(): ?string
{
return $this->filename;
}
public function getContentType(): string
{
return implode('/', [$this->getMediaType(), $this->getMediaSubtype()]);
}
private function generateContentId(): string
{
return bin2hex(random_bytes(16)).'@symfony';
}
public function __sleep(): array
{
// converts the body to a string
parent::__sleep();
$this->_parent = [];
foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) {
$r = new \ReflectionProperty(TextPart::class, $name);
$this->_parent[$name] = $r->getValue($this);
}
$this->_headers = $this->getHeaders();
return ['_headers', '_parent', 'filename', 'mediaType'];
}
/**
* @return void
*/
public function __wakeup()
{
$r = new \ReflectionProperty(AbstractPart::class, 'headers');
$r->setValue($this, $this->_headers);
unset($this->_headers);
if (!\is_array($this->_parent)) {
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) {
if (null !== $this->_parent[$name] && !\is_string($this->_parent[$name]) && !$this->_parent[$name] instanceof File) {
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
$r = new \ReflectionProperty(TextPart::class, $name);
$r->setValue($this, $this->_parent[$name]);
}
unset($this->_parent);
}
}
-51
View File
@@ -1,51 +0,0 @@
<?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\Mime\Part;
use Symfony\Component\Mime\MimeTypes;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class File
{
private static MimeTypes $mimeTypes;
public function __construct(
private string $path,
private ?string $filename = null,
) {
}
public function getPath(): string
{
return $this->path;
}
public function getContentType(): string
{
$ext = strtolower(pathinfo($this->path, \PATHINFO_EXTENSION));
self::$mimeTypes ??= new MimeTypes();
return self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream';
}
public function getSize(): int
{
return filesize($this->path);
}
public function getFilename(): string
{
return $this->filename ??= basename($this->getPath());
}
}
@@ -1,72 +0,0 @@
<?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\Mime\Part;
use Symfony\Component\Mime\Message;
use Symfony\Component\Mime\RawMessage;
/**
* @final
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class MessagePart extends DataPart
{
private RawMessage $message;
public function __construct(RawMessage $message)
{
if ($message instanceof Message) {
$name = $message->getHeaders()->getHeaderBody('Subject').'.eml';
} else {
$name = 'email.eml';
}
parent::__construct('', $name);
$this->message = $message;
}
public function getMediaType(): string
{
return 'message';
}
public function getMediaSubtype(): string
{
return 'rfc822';
}
public function getBody(): string
{
return $this->message->toString();
}
public function bodyToString(): string
{
return $this->getBody();
}
public function bodyToIterable(): iterable
{
return $this->message->toIterable();
}
public function __sleep(): array
{
return ['message'];
}
public function __wakeup(): void
{
$this->__construct($this->message);
}
}
@@ -1,25 +0,0 @@
<?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\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
final class AlternativePart extends AbstractMultipartPart
{
public function getMediaSubtype(): string
{
return 'alternative';
}
}
@@ -1,31 +0,0 @@
<?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\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
use Symfony\Component\Mime\Part\MessagePart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
final class DigestPart extends AbstractMultipartPart
{
public function __construct(MessagePart ...$parts)
{
parent::__construct(...$parts);
}
public function getMediaSubtype(): string
{
return 'digest';
}
}
@@ -1,108 +0,0 @@
<?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\Mime\Part\Multipart;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\TextPart;
/**
* Implements RFC 7578.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
final class FormDataPart extends AbstractMultipartPart
{
private array $fields = [];
/**
* @param array<string|array|DataPart> $fields
*/
public function __construct(array $fields = [])
{
parent::__construct();
$this->fields = $fields;
// HTTP does not support \r\n in header values
$this->getHeaders()->setMaxLineLength(\PHP_INT_MAX);
}
public function getMediaSubtype(): string
{
return 'form-data';
}
public function getParts(): array
{
return $this->prepareFields($this->fields);
}
private function prepareFields(array $fields): array
{
$values = [];
$prepare = function ($item, $key, $root = null) use (&$values, &$prepare) {
if (null === $root && \is_int($key) && \is_array($item)) {
if (1 !== \count($item)) {
throw new InvalidArgumentException(sprintf('Form field values with integer keys can only have one array element, the key being the field name and the value being the field value, %d provided.', \count($item)));
}
$key = key($item);
$item = $item[$key];
}
$fieldName = null !== $root ? sprintf('%s[%s]', $root, $key) : $key;
if (\is_array($item)) {
array_walk($item, $prepare, $fieldName);
return;
}
if (!\is_string($item) && !$item instanceof TextPart) {
throw new InvalidArgumentException(sprintf('The value of the form field "%s" can only be a string, an array, or an instance of TextPart, "%s" given.', $fieldName, get_debug_type($item)));
}
$values[] = $this->preparePart($fieldName, $item);
};
array_walk($fields, $prepare);
return $values;
}
private function preparePart(string $name, string|TextPart $value): TextPart
{
if (\is_string($value)) {
return $this->configurePart($name, new TextPart($value, 'utf-8', 'plain', '8bit'));
}
return $this->configurePart($name, $value);
}
private function configurePart(string $name, TextPart $part): TextPart
{
static $r;
$r ??= new \ReflectionProperty(TextPart::class, 'encoding');
$part->setDisposition('form-data');
$part->setName($name);
// HTTP does not support \r\n in header values
$part->getHeaders()->setMaxLineLength(\PHP_INT_MAX);
$r->setValue($part, '8bit');
return $part;
}
}
@@ -1,25 +0,0 @@
<?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\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
final class MixedPart extends AbstractMultipartPart
{
public function getMediaSubtype(): string
{
return 'mixed';
}
}
@@ -1,55 +0,0 @@
<?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\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
use Symfony\Component\Mime\Part\AbstractPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
final class RelatedPart extends AbstractMultipartPart
{
private AbstractPart $mainPart;
public function __construct(AbstractPart $mainPart, AbstractPart $part, AbstractPart ...$parts)
{
$this->mainPart = $mainPart;
$this->prepareParts($part, ...$parts);
parent::__construct($part, ...$parts);
}
public function getParts(): array
{
return array_merge([$this->mainPart], parent::getParts());
}
public function getMediaSubtype(): string
{
return 'related';
}
private function generateContentId(): string
{
return bin2hex(random_bytes(16)).'@symfony';
}
private function prepareParts(AbstractPart ...$parts): void
{
foreach ($parts as $part) {
if (!$part->getHeaders()->has('Content-ID')) {
$part->getHeaders()->setHeaderBody('Id', 'Content-ID', $this->generateContentId());
}
}
}
}
@@ -1,111 +0,0 @@
<?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\Mime\Part;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Sebastiaan Stok <s.stok@rollerscapes.net>
*/
class SMimePart extends AbstractPart
{
/** @internal */
protected Headers $_headers;
private iterable|string $body;
private string $type;
private string $subtype;
private array $parameters;
public function __construct(iterable|string $body, string $type, string $subtype, array $parameters)
{
parent::__construct();
$this->body = $body;
$this->type = $type;
$this->subtype = $subtype;
$this->parameters = $parameters;
}
public function getMediaType(): string
{
return $this->type;
}
public function getMediaSubtype(): string
{
return $this->subtype;
}
public function bodyToString(): string
{
if (\is_string($this->body)) {
return $this->body;
}
$body = '';
foreach ($this->body as $chunk) {
$body .= $chunk;
}
$this->body = $body;
return $body;
}
public function bodyToIterable(): iterable
{
if (\is_string($this->body)) {
yield $this->body;
return;
}
$body = '';
foreach ($this->body as $chunk) {
$body .= $chunk;
yield $chunk;
}
$this->body = $body;
}
public function getPreparedHeaders(): Headers
{
$headers = clone parent::getHeaders();
$headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype());
foreach ($this->parameters as $name => $value) {
$headers->setHeaderParameter('Content-Type', $name, $value);
}
return $headers;
}
public function __sleep(): array
{
// convert iterables to strings for serialization
if (is_iterable($this->body)) {
$this->body = $this->bodyToString();
}
$this->_headers = $this->getHeaders();
return ['_headers', 'body', 'type', 'subtype', 'parameters'];
}
public function __wakeup(): void
{
$r = new \ReflectionProperty(AbstractPart::class, 'headers');
$r->setValue($this, $this->_headers);
unset($this->_headers);
}
}
@@ -1,244 +0,0 @@
<?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\Mime\Part;
use Symfony\Component\Mime\Encoder\Base64ContentEncoder;
use Symfony\Component\Mime\Encoder\ContentEncoderInterface;
use Symfony\Component\Mime\Encoder\EightBitContentEncoder;
use Symfony\Component\Mime\Encoder\QpContentEncoder;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class TextPart extends AbstractPart
{
/** @internal */
protected Headers $_headers;
private static array $encoders = [];
/** @var resource|string|File */
private $body;
private ?string $charset;
private string $subtype;
private ?string $disposition = null;
private ?string $name = null;
private string $encoding;
private ?bool $seekable = null;
/**
* @param resource|string|File $body Use a File instance to defer loading the file until rendering
*/
public function __construct($body, ?string $charset = 'utf-8', string $subtype = 'plain', ?string $encoding = null)
{
parent::__construct();
if (!\is_string($body) && !\is_resource($body) && !$body instanceof File) {
throw new \TypeError(sprintf('The body of "%s" must be a string, a resource, or an instance of "%s" (got "%s").', self::class, File::class, get_debug_type($body)));
}
if ($body instanceof File) {
$path = $body->getPath();
if ((is_file($path) && !is_readable($path)) || is_dir($path)) {
throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path));
}
}
$this->body = $body;
$this->charset = $charset;
$this->subtype = $subtype;
$this->seekable = \is_resource($body) ? stream_get_meta_data($body)['seekable'] && 0 === fseek($body, 0, \SEEK_CUR) : null;
if (null === $encoding) {
$this->encoding = $this->chooseEncoding();
} else {
if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) {
throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding));
}
$this->encoding = $encoding;
}
}
public function getMediaType(): string
{
return 'text';
}
public function getMediaSubtype(): string
{
return $this->subtype;
}
/**
* @param string $disposition one of attachment, inline, or form-data
*
* @return $this
*/
public function setDisposition(string $disposition): static
{
$this->disposition = $disposition;
return $this;
}
/**
* @return ?string null or one of attachment, inline, or form-data
*/
public function getDisposition(): ?string
{
return $this->disposition;
}
/**
* Sets the name of the file (used by FormDataPart).
*
* @return $this
*/
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
/**
* Gets the name of the file.
*/
public function getName(): ?string
{
return $this->name;
}
public function getBody(): string
{
if ($this->body instanceof File) {
return file_get_contents($this->body->getPath());
}
if (null === $this->seekable) {
return $this->body;
}
if ($this->seekable) {
rewind($this->body);
}
return stream_get_contents($this->body) ?: '';
}
public function bodyToString(): string
{
return $this->getEncoder()->encodeString($this->getBody(), $this->charset);
}
public function bodyToIterable(): iterable
{
if ($this->body instanceof File) {
$path = $this->body->getPath();
if (false === $handle = @fopen($path, 'r', false)) {
throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path));
}
yield from $this->getEncoder()->encodeByteStream($handle);
} elseif (null !== $this->seekable) {
if ($this->seekable) {
rewind($this->body);
}
yield from $this->getEncoder()->encodeByteStream($this->body);
} else {
yield $this->getEncoder()->encodeString($this->body);
}
}
public function getPreparedHeaders(): Headers
{
$headers = parent::getPreparedHeaders();
$headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype());
if ($this->charset) {
$headers->setHeaderParameter('Content-Type', 'charset', $this->charset);
}
if ($this->name && 'form-data' !== $this->disposition) {
$headers->setHeaderParameter('Content-Type', 'name', $this->name);
}
$headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding);
if (!$headers->has('Content-Disposition') && null !== $this->disposition) {
$headers->setHeaderBody('Parameterized', 'Content-Disposition', $this->disposition);
if ($this->name) {
$headers->setHeaderParameter('Content-Disposition', 'name', $this->name);
}
}
return $headers;
}
public function asDebugString(): string
{
$str = parent::asDebugString();
if (null !== $this->charset) {
$str .= ' charset: '.$this->charset;
}
if (null !== $this->disposition) {
$str .= ' disposition: '.$this->disposition;
}
return $str;
}
private function getEncoder(): ContentEncoderInterface
{
if ('8bit' === $this->encoding) {
return self::$encoders[$this->encoding] ??= new EightBitContentEncoder();
}
if ('quoted-printable' === $this->encoding) {
return self::$encoders[$this->encoding] ??= new QpContentEncoder();
}
return self::$encoders[$this->encoding] ??= new Base64ContentEncoder();
}
private function chooseEncoding(): string
{
if (null === $this->charset) {
return 'base64';
}
return 'quoted-printable';
}
public function __sleep(): array
{
// convert resources to strings for serialization
if (null !== $this->seekable) {
$this->body = $this->getBody();
$this->seekable = null;
}
$this->_headers = $this->getHeaders();
return ['_headers', 'body', 'charset', 'subtype', 'disposition', 'name', 'encoding'];
}
/**
* @return void
*/
public function __wakeup()
{
$r = new \ReflectionProperty(AbstractPart::class, 'headers');
$r->setValue($this, $this->_headers);
unset($this->_headers);
}
}